Co robi słowo kluczowe ʻis` w maszynie?


114

Natknąłem się na kod, który wygląda tak:

export function foo(arg: string): arg is MyType {
    return ...
}

Nie udało mi się wyszukać isani w dokumentach, ani w Google, jest to dość powszechne słowo i pojawia się w zasadzie na każdej stronie.

Co robi słowo kluczowe w tym kontekście?

Odpowiedzi:


125
function isString(test: any): test is string{
    return typeof test === "string";
}

function example(foo: any){
    if(isString(foo)){
        console.log("it is a string" + foo);
        console.log(foo.length); // string function
    }
}
example("hello world");

Używając predykatu typu „test is string” w powyższym formacie (zamiast po prostu używać wartości logicznej dla typu zwracanego, po wywołaniu funkcji isString (), jeśli funkcja zwróci wartość true, TypeScript zawęzi typ do ciągu w dowolnym bloku chronionym przez wywołanie funkcji. Kompilator pomyśli, że foo jest łańcuchem znaków w bloku chronionym poniżej (i TYLKO w bloku chronionym poniżej)

{
    console.log("it is a string" + foo);
    console.log(foo.length); // string function
}

Predykat typu jest używany tylko w czasie kompilacji. Wynikowy plik .js (środowisko wykonawcze) nie będzie miało różnicy, ponieważ nie uwzględnia TYPU.

Różnice zilustruję w czterech poniższych przykładach.

Np. 1: powyższy przykładowy kod nie będzie miał błędu kompilacji i błędu wykonania.

Np. 2: poniższy przykładowy kod będzie miał błąd kompilacji (jak również błąd wykonania), ponieważ TypeScript zawęził typ do string i sprawdził, że toExponential nie należy do metody string.

function example(foo: any){
    if(isString(foo)){
        console.log("it is a string" + foo);
        console.log(foo.length);
        console.log(foo.toExponential(2));
    }
}

Np. 3: poniższy przykładowy kod nie ma błędu kompilacji, ale będzie miał błąd wykonania, ponieważ TypeScript zawęzi typ TYLKO do łańcucha w chronionym bloku, ale nie po, dlatego foo.toExponential nie utworzy błędu kompilacji (TypeScript nie uważa, że ​​tak jest typu string). Jednak w czasie wykonywania ciąg nie ma metody toExponential, więc wystąpi błąd w czasie wykonywania.

function example(foo: any){
    if(isString(foo)){
        console.log("it is a string" + foo);
        console.log(foo.length);
    }
    console.log(foo.toExponential(2));
}

Np. 4: jeśli nie użyjemy „test is string” (predykat typu), TypeScript nie zawęzi typu w chronionym bloku, a poniższy przykładowy kod nie będzie miał błędu kompilacji, ale będzie miał błąd wykonania.

function isString(test: any): boolean{
    return typeof test === "string";
}
function example(foo: any){
    if(isString(foo)){
        console.log("it is a string" + foo);
        console.log(foo.length);
        console.log(foo.toExponential(2));
    }
}

Wniosek jest taki, że „test to string” (predykat typu) jest używany w czasie kompilacji, aby poinformować programistów, że kod będzie miał szansę na wystąpienie błędu w czasie wykonywania. W przypadku javascript programiści nie ZNAJĄ błędu w czasie kompilacji. Jest to zaleta używania TypeScript.


12

Jedyne zastosowanie, jakie znam, to użycie twojego przykładu: określenie "predykatu typu" ( arg is MyType) w zdefiniowanej przez użytkownika Ochronie typów

Zobacz Ochrona typów zdefiniowanych przez użytkownika w tym dokumencie

Oto kolejne odniesienie


1
Widziałem to również w dokumentach, co za dziwna decyzja projektowa, ten przypadek można całkowicie rozwiązać, zwracając typ, booleanprawda?
— benjaminz

2
@benjaminz To może uzasadniać własne pytanie na temat SO, ale mogę pokazać szybki przykład, jak się różnią. Słowo iskluczowe faktycznie rzutuje typ i może wychwycić błędy typu w dalszej części kodu. Zobacz ten przykład, aby uzyskać więcej informacji.
— styfle

@benjaminz Nie widzę, jak mógłby to zrobić boolean. Maszynopis musi wiedzieć, że funkcja, do której przekazujesz obiekt, działa jak ochrona typów. Jeśli po prostu zwraca typ true lub false, w jaki sposób Typescript może wiedzieć, że jest to rzeczywiście strażnik typu, a nie tylko dowolna funkcja, która zwraca wartość true, jeśli obiekt jest prawdziwy. Skąd będzie wiedzieć, czy zawęzić typ obiektu? Po drugie, skąd może wiedzieć, do jakiego typu należy zawęzić typ obiektu? A jeśli parametr jest jednym z trzech typów? Musi wiedzieć, że trueodpowiada określonemu typowi.
— Puszkin
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.