Was macht das Schlüsselwort "is" im Typoskript?


100

Ich bin auf einen Code gestoßen, der so aussieht:

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

Ich konnte isweder in den Dokumenten noch in Google suchen. Es ist ein ziemlich verbreitetes Wort und wird auf praktisch jeder Seite angezeigt.

Was macht das Schlüsselwort in diesem Zusammenhang?

Antworten:


112
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");

Wenn Sie das Typprädikat "test is string" im obigen Format verwenden (anstatt nur boolean für den Rückgabetyp zu verwenden, wird TypeScript nach dem Aufruf von isString () den Typ auf Zeichenfolge in einem von a geschützten Block eingrenzen Aufruf der Funktion. Der Compiler wird denken, dass foo eine Zeichenfolge im untergeschützten Block ist (und NUR im untergeschützten Block).

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

Das Typprädikat wird nur zur Kompilierungszeit verwendet. Die Ergebnis-JS-Datei (Laufzeit) hat keinen Unterschied, da der TYP nicht berücksichtigt wird.

Ich werde die Unterschiede in den folgenden vier Beispielen veranschaulichen.

Beispiel 1: Der obige Beispielcode weist keinen Kompilierungs- und Laufzeitfehler auf.

Beispiel 2: Der folgende Beispielcode weist einen Kompilierungsfehler (sowie einen Laufzeitfehler) auf, da TypeScript den Typ auf Zeichenfolge eingegrenzt und überprüft hat, dass toExponential nicht zur Zeichenfolgenmethode gehört.

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

Beispiel 3: Der folgende Beispielcode hat keinen Kompilierungsfehler, aber einen Laufzeitfehler, da TypeScript den Typ NUR auf eine Zeichenfolge im geschützten Block eingrenzt, jedoch nicht danach. Daher erstellt foo.toExponential keinen Kompilierungsfehler (TypeScript glaubt nicht, dass dies der Fall ist) ein String-Typ). Zur Laufzeit verfügt die Zeichenfolge jedoch nicht über die Methode toExponential, sodass ein Laufzeitfehler auftritt.

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

Beispiel 4: Wenn wir nicht "test is string" (Typprädikat) verwenden, wird TypeScript den Typ im geschützten Block nicht eingrenzen und der folgende Beispielcode hat keinen Kompilierungsfehler, aber einen Laufzeitfehler.

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));
    }
}

Die Schlussfolgerung ist, dass "test is string" (Typprädikat) in der Kompilierungszeit verwendet wird, um den Entwicklern mitzuteilen, dass der Code möglicherweise einen Laufzeitfehler aufweist. Bei Javascript kennen die Entwickler den Fehler in der Kompilierungszeit nicht. Dies ist der Vorteil der Verwendung von TypeScript.


11

Die einzige mir bekannte Verwendung ist die Ihres Beispiels: Angabe eines "Typprädikats" ( arg is MyType) in einem benutzerdefinierten Typschutz

Siehe Benutzerdefinierte Typschutzvorrichtungen in dieser Referenz

Hier ist eine weitere Referenz


1
Ich habe dies auch in den Dokumenten gesehen. Was für eine bizarre Designentscheidung, dieser Fall kann vollständig durch Rückgabe eines Typs behandelt werden, booleanoder?
— Benjamin

2
@benjaminz Dies könnte eine eigene Frage zu SO rechtfertigen, aber ich kann Ihnen ein kurzes Beispiel dafür zeigen, wie unterschiedlich sie sind. Das isSchlüsselwort wandelt den Typ tatsächlich um und kann später im Code Typfehler abfangen. In diesem Beispiel finden Sie weitere Informationen.
— Styfle

@benjaminz Ich sehe nicht, wie es von einem Booleschen behandelt werden könnte. Typoskript muss wissen, dass die Funktion, an die Sie ein Objekt übergeben, wie ein Typschutz funktioniert. Wenn Typescript nur den Typ true oder false zurückgibt, wie kann Typescript dann erkennen, dass es sich tatsächlich um einen Type Guard handelt und nicht nur um eine beliebige Funktion, die true zurückgibt, wenn das Objekt wahr ist. Woher weiß es, den Objekttyp einzugrenzen? Zweitens, wie kann es wissen, auf welchen Typ der Objekttyp eingegrenzt werden soll? Was ist, wenn der Parameter einer von drei Typen ist? Es muss wissen, dass dies trueeinem bestimmten Typ entspricht.
— Puschkin
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.