TypeScript-Typzusicherung
Typzusicherung ist ein Mechanismus, der dem Compiler sagt: „Ich kenne den Typ dieses Werts besser als du.“ Sie ermöglicht Entwicklern, die Ergebnisse der Typinferenz von TypeScript manuell zu überschreiben, ähnlich der Typkonvertierung in anderen Sprachen, abersie wirkt sich nur während der Kompilierungsphase aus und erzeugt keinen Laufzeitcode.。
Zwei Syntaxformen
Es gibt zwei Schreibweisen für Typzusicherungen; es wird empfohlen, durchgängig dieasSyntax zu verwenden; die Winkelklammer-Syntax steht im Konflikt mit der Tag-Syntax in JSX-Dateien.
Beispiel
const str1: any = "hello";
const len1: number = (<string>str1).length;
// ② as-Syntax (empfohlen)
const str2: any = "world";
const len2: number = (str2 as string).length;
console.log(len1); // 5
console.log(len2); // 5
Ausgabe:
5 5
Hinweis:In React's
.tsxDateien, die Winkelklammer-Syntax kollidiert mit JSX-Tags, daher muss dieasSyntax verwendet werden.
Häufige Anwendungsfälle
1. Umgang mit any / unknown-Typen
Daten, die aus externen Schnittstellen, JSON-Parsing und anderen Szenarien stammen, sind normalerweiseany; Assertions können Typ-Hinweise wiederherstellen.
Beispiel
// Als bestimmten Typ assertieren, um Typ-Hinweise zu erhalten
const user = response as { name: string; age: number };
console.log(user.name); // Alice
console.log(user.age); // 25
Ausgabe:
Alice 25
2. Union-Typen eingrenzen
Wenn Sie den spezifischen Zweig eines Union-Typs kennen, der Compiler ihn aber nicht automatisch bestimmen kann, können Sie eine Assertion verwenden, um den Typ eindeutig anzugeben.
Beispiel
| { kind: "circle"; radius: number }
| { kind: "rect"; width: number; height: number };
function getArea(shape: Shape): number {
if (shape.kind === "circle") {
return Math.PI * (shape as { kind: "circle"; radius: number }).radius ** 2;
}
const rect = shape as { kind: "rect"; width: number; height: number };
return rect.width * rect.height;
}
console.log(getArea({ kind: "circle", radius: 5 }).toFixed(2)); // 78.54
console.log(getArea({ kind: "rect", width: 4, height: 6 })); // 24
Ausgabe:
78.54 24
Tipp:Bevorzuge die Verwendung von Type Guards (
typeof/instanceof/ diskriminante Eigenschaften) um Typen einzugrenzen; verwende Assertions nur in Szenarien, die Guards nicht abdecken können.
3. DOM-Elemente manipulieren
document.querySelectorDer Rückgabetyp istElement | null; erst nachdem es als spezifischen Elementtyp assertiert wurde, kannst du auf seine exklusiven Eigenschaften zugreifen.
Beispiel
const input = document.querySelector("#username") as HTMLInputElement;
// Nach der Assertion kannst du auf die exklusiven Eigenschaften von HTMLInputElement zugreifen
// console.log(input.value);
// Sicherer Ansatz: zuerst auf null prüfen, dann assertieren
const btn = document.querySelector("#submit");
if (btn) {
(btn as HTMLButtonElement).disabled = true;
}
Nicht-Null-Assertion !
Add!nach dem Wert, um dem Compiler mitzuteilen, dass der Wert nichtnulloderundefined; geeignet für Szenarien, in denen Sie sicher sind, dass er nicht null ist, aber der Compiler es nicht ableiten kann.
Beispiel
// Verwende !, um zu bestätigen, dass str definitiv einen Wert hat
console.log(str!.length);
}
// Läuft normal
printLength("hello"); // 5
// Laufzeitfehler: Cannot read properties of undefined
// printLength();
Ausgabe:
5
Warnung:Die Non-Null-Assertion umgeht die Nullprüfung des Compilers; wenn der tatsächliche Wert vorliegt
null/undefined, wird zur Laufzeit trotzdem ein Fehler ausgelöst. Wenn die Bedingungen es zulassen, bevorzugen Sie die Verwendung von Optional Chaining?.stattdessen.
Const-Assertion as const
as constLeitet Literale als die engsten readonly-Literaltypen ab, häufig verwendet zum Definieren von Enum-Werten, Konfigurationskonstanten und Tupeln.
Beispiel
const colors1 = ["red", "green", "blue"];
colors1.push("yellow"); // Erlaubt
// as const: als readonly ["red", "green", "blue"] abgeleitet; sowohl Elemente als auch Länge sind unveränderlich
const colors2 = ["red", "green", "blue"] as const;
// colors2.push("yellow"); // Fehler: Kann nicht auf ein schreibgeschütztes Array pushen
// Dasselbe gilt für Objekte: Alle Eigenschaften werden zu readonly-Literaltypen
const config = {
host: "localhost",
port: 3000
} as const;
// config.port = 8080; // Fehler: readonly-Eigenschaft kann nicht geändert werden
console.log(colors2); // ['red', 'green', 'blue']
console.log(config.host); // localhost
console.log(config.port); // 3000
Ausgabe:
['red', 'green', 'blue'] localhost 3000
Typzusicherung ist keine Typkonvertierung
Eine Typzusicherung wirkt sich nur auf die Typprüfung des Compilers aus und erzeugt nach der Kompilierung keinen Konvertierungscode. Beim Zusichern"42"asnumber, zur Laufzeit ist es immer noch ein String.
Beispiel
// Als number zugesichert, aber zur Laufzeit ist es immer noch ein String
const wrongNum = strNum as number;
console.log(typeof wrongNum); // string (keine Zahl!)
console.log(wrongNum + 1); // 421 (String-Verkettung, keine numerische Addition)
// Echte Typkonvertierung erfordert Konvertierungsfunktionen
const realNum = Number(strNum);
console.log(typeof realNum); // number
console.log(realNum + 1); // 43
Ausgabe:
string 421 number 43
Doppelte Assertion
Wenn es keine Überlappung zwischen zwei Typen gibt, verweigert TypeScript eine direkte Assertion. In diesem Fall kannst duunknownals Zwischenstufe verwenden, aber dies ist eine gefährliche Operation und sollte nach Möglichkeit vermieden werden.
Beispiel
// Direkte Assertion: number und string überschneiden sich nicht, der Compiler meldet einen Fehler
// const str = num as string;
// Doppelte Assertion: zuerst als unknown assertieren, dann als Zieltyp assertieren
const str = num as unknown as string;
console.log(str); // 42
console.log(typeof str); // number (Laufzeittyp unverändert; Assertion wirkt nur zur Kompilierzeit)
Ausgabe:
42 number
Warnung:Die doppelte Assertion umgeht das Typsystem von TypeScript vollständig und kann leicht Laufzeitfehler verursachen. Verwende sie nur in Sonderfällen wie ungenauen Typen in Drittanbieter-Bibliotheken und vermerke den Grund im Code.
Vergleich der Assertion-Methoden
| Assertion-Methode | Syntax | Typisches Szenario | Risiko |
|---|---|---|---|
| as-Assertion | value as Type | Umwandlung von any in einen bestimmten Typ, DOM-Operationen | Niedrig (Überlappungsprüfung vorhanden) |
| Non-Null-Assertion | value! | Bestätigung von non-null/undefined | Mittel (überspringt Nullprüfung) |
| Const-Assertion | value as const | Literal-Konstanten, Enum-Werte | Keine |
| Doppelte Assertion | value as unknown as T | Erzwungene Konvertierung, wenn Typen keine Überlappung haben | Hoch (umgeht Prüfungen vollständig) |
Zusammenfassung
- Syntaxauswahl:Verwenden Sie durchgängig die
asSyntax und vermeiden Sie die Winkelklammer-Syntax in JSX - Assertion vs. Konvertierung:Assertion wirkt sich nur auf Compile-Time-Typen aus und erzeugt keinen Laufzeitcode; echte Wertkonvertierung erfordert die Verwendung von
Number()、String()und anderen ähnlichen Funktionen - Non-Null-Assertion:Bevor Sie es verwenden
!, stellen Sie sicher, dass der Wert wirklich nicht null ist; andernfalls tritt zur Laufzeit ein Fehler auf. Wenn die Bedingungen es zulassen, verwenden Sie vorzugsweise?. - Const-Assertion:
as constist eine sichere und praktische Assertion, empfohlen für Konfigurationsobjekte und konstante Arrays - Doppelte Assertion:ist das letzte Mittel; man muss den Grund kommentieren, wenn man sie verwendet
Weitere verwandte Inhalte