Website-Suche

In TypeScript, was ist der ! (Ausrufezeichen/Bang) Operator beim Dereferenzieren eines Mitglieds?


Beim Betrachten des Quellcodes einer TSLint-Regel bin ich auf die folgende Aussage gestoßen:

if (node.parent!.kind === ts.SyntaxKind.ObjectLiteralExpression) {
    return;
}

Beachte den !-Operator nach node.parent. Interessant!

Ich habe zuerst versucht, die Datei lokal mit meiner momentan installierten Version von TS (1.5.3) zu kompilieren. Der resultierende Fehler wies auf die genaue Position des Ausrufezeichens hin:

tsc --noImplicitAny memberAccessRule.ts 
noPublicModifierRule.ts(57,24): error TS1005: ')' expected.

Als Nächstes habe ich auf die neueste TS (2.1.6) aktualisiert, die es ohne Probleme kompiliert hat. Es scheint also eine Funktion von TS 2.x zu sein. Aber die Transpilierung hat das Ausrufezeichen vollständig ignoriert, was zu folgendem JS führte:

if (node.parent.kind === ts.SyntaxKind.ObjectLiteralExpression) {
    return;
}

Mein Google-Fu hat mich bisher im Stich gelassen.

Was ist der Ausrufezeichenoperator von TS und wie funktioniert er?

Antwort #1

Das ist der Non-Null-Assertion-Operator. Er ist eine Möglichkeit, dem Compiler zu sagen: „Dieser Ausdruck kann hier nicht null oder undefined sein, also beschwere dich nicht über die Möglichkeit, dass er null oder undefined sein könnte.“ Manchmal ist der Typprüfer nicht in der Lage, diese Bestimmung selbst zu treffen.

Es wird in den TypeScript-Release-Notes erklärt:

Ein neuer ! Postfix-Ausdrucksoperator kann verwendet werden, um sicherzustellen, dass sein Operant nicht null und nicht undefiniert ist, in Kontexten, in denen der Typprüfer diese Tatsache nicht feststellen kann. Insbesondere produziert die Operation x! einen Wert des Typs von x mit ausgeschlossenen null und undefined. Ähnlich wie Typumwandlungen in den Formen <T>x und x as T wird der !-Nicht-Null-Assertionsoperator einfach im ausgegebenen JavaScript-Code entfernt.

Ich finde die Verwendung des Begriffs „assert“ in dieser Erklärung ein wenig irreführend. Es ist „assert“ im Sinne von der Entwickler behauptet es, nicht im Sinne davon, dass ein Test durchgeführt wird. Die letzte Zeile zeigt tatsächlich an, dass kein JavaScript-Code erzeugt wird.

Antwort #2

Louis' Antwort ist großartig, aber ich dachte, ich würde versuchen, sie knapp zusammenzufassen:

Der Bang-Operator sagt dem Compiler, die Einschränkung "nicht null" vorübergehend zu lockern, die er sonst möglicherweise verlangen würde. Er sagt dem Compiler: "Als Entwickler weiß ich besser als du, dass diese Variable im Moment nicht null sein kann."

Antwort #3

Nicht-Null-Bestätigungsoperator

Mit dem Nicht-Null-Assertion-Operator können wir dem Compiler explizit mitteilen, dass ein Ausdruck einen Wert ungleich null oder undefined hat. Dies kann nützlich sein, wenn der Compiler den Typ nicht mit Sicherheit ableiten kann, wir jedoch mehr Informationen haben als der Compiler.

Beispiel

TS-Code

function simpleExample(nullableArg: number | undefined | null) {
   const normal: number = nullableArg; 
    //   Compile err: 
    //   Type 'number | null | undefined' is not assignable to type 'number'.
    //   Type 'undefined' is not assignable to type 'number'.(2322)

   const operatorApplied: number = nullableArg!; 
    // compiles fine because we tell compiler that null | undefined are excluded 
}

Kompilierter JS-Code

Beachten Sie, dass JS das Konzept des Non-Null Assertion Operators nicht kennt, da dies eine TS-Funktion ist.

"use strict";
function simpleExample(nullableArg) {
    const normal = nullableArg;
    const operatorApplied = nullableArg;
}

Antwort #4

Kurze Antwort

Der Non-Null-Assertion-Operator (!) hilft dem Compiler, dass ich sicher bin, dass diese Variable nicht null oder undefiniert ist.

let obj: { field: SampleType } | null | undefined;

... // some code

// the type of sampleVar is SampleType
let sampleVar = obj!.field; // we tell compiler we are sure obj is not null & not undefined so the type of sampleVar is SampleType

Verwandte Artikel