TypeScript Utility-Typen
Hilfstypen sind eine Reihe integrierter fortgeschrittener Typen in TypeScript.
Sie helfen Entwicklern, Typen schnell zu erstellen und umzuwandeln, wodurch die Wiederverwendbarkeit des Codes und die Typsicherheit verbessert werden.
Hilfstypen sind im Wesentlichen generische Typen, die durch Mapped Types und Conditional Types implementiert werden.
Warum werden Hilfstypen benötigt?
In der tatsächlichen TypeScript-Entwicklung müssen wir oft neue Typen auf Basis vorhandener Typen erstellen.
Diese Typen manuell zu erstellen ist nicht nur mühsam, sondern auch fehleranfällig.
Utility-Typen bieten eine deklarative Möglichkeit, Typen umzuwandeln und zu erstellen, was die Entwicklungseffizienz erheblich verbessert.
Konzepterklärung:Utility-Typen sind eine Reihe vordefinierter generischer Typen in TypeScript. Sie verwenden Mapped Types und Conditional Types, um Typen umzuwandeln und zu erzeugen.
Partial<T> - Optionale Eigenschaften
Partial setzt alle Eigenschaften des Typs T auf optional.
Dies ist sehr nützlich beim Erstellen teilweise aktualisierter Objekte oder bei der Verarbeitung von Formulardaten.
Beispiel
interface User {
// Benutzer-ID
id: number;
// Benutzername
name: string;
// Benutzer-E-Mail
email: string;
}
// Partial: macht alle Eigenschaften optional
// Alle Eigenschaften im transformierten Typ sind optional
type PartialUser = Partial<User>;
// Verwenden Sie den Typ PartialUser
// Sie können nur einige Eigenschaften angeben, nicht alle
var user: PartialUser = { name: "Alice" };
console.log("Partieller Benutzer: " + JSON.stringify(user));
Run result:
部分用户: {"name":"Alice"}
Anwendungsszenarien:Partial wird häufig verwendet, um Objektdaten zu aktualisieren. Zum Beispiel: Wenn nur ein Teil der Informationen eines Benutzers aktualisiert wird, müssen Sie nicht das gesamte Benutzerobjekt übergeben.
Required<T> - Erforderliche Eigenschaften
Required ist das Gegenteil von Partial; es macht alle optionalen Eigenschaften erforderlich.
Verwenden Sie es, wenn Sie sicherstellen müssen, dass ein Objekt alle Eigenschaften enthält.
Beispiel
interface Config {
// Serveradresse
host?: string;
// Portnummer
port?: number;
}
// Required: macht alle optionalen Eigenschaften erforderlich
// Alle Eigenschaften im transformierten Typ sind erforderlich
type RequiredConfig = Required<Config>;
// Verwenden Sie den Typ RequiredConfig
// Alle Eigenschaften müssen angegeben werden
var config: RequiredConfig = { host: "localhost", port: 8080 };
console.log("Konfiguration: " + JSON.stringify(config));
Run result:
配置: {"host":"localhost","port":8080}
Hinweis:Required entfernt nicht nur den optionalen Marker (?), sondern auch den readonly-Modifizierer.
Readonly<T> - Readonly-Eigenschaften
Readonly setzt alle Eigenschaften auf readonly.
Es ist sehr nützlich beim Erstellen von Objekten, die nach der Erstellung nicht geändert werden können.
Beispiel
interface User {
// Benutzername
name: string;
// Benutzeralter
age: number;
}
// Readonly: setzt alle Eigenschaften auf readonly
// Keine der Eigenschaften im transformierten Typ kann geändert werden
type ReadonlyUser = Readonly<User>;
// Erstelle ein readonly-Benutzerobjekt
var user: ReadonlyUser = { name: "Alice", age: 25 };
// Der Versuch, eine readonly-Eigenschaft zu ändern, verursacht einen Fehler
// user.name = "Bob"; // Fehler: readonly-Eigenschaft kann nicht geändert werden
console.log("Readonly-Benutzer: " + JSON.stringify(user));
Anwendungsszenarien:Readonly wird häufig verwendet, um Konfigurationsobjekte, Enum-Wert-Zuordnungen und andere Daten zu definieren, die nicht geändert werden sollten.
Pick<T, K> - Eigenschaften auswählen
Pick wählt die angegebenen Eigenschaften K aus dem Typ T aus, um einen neuen Typ zu bilden.
Verwenden Sie es, wenn Sie nur einige Eigenschaften eines Typs benötigen.
Beispiel
interface User {
// Benutzer-ID
id: number;
// Benutzername
name: string;
// Benutzer-E-Mail
email: string;
// Benutzerpasswort
password: string;
}
// Pick: die angegebenen Eigenschaften auswählen, um einen neuen Typ zu bilden
// Die Eigenschaften id und name aus User auswählen
type UserBasicInfo = Pick<User, "id" | "name">;
// Den ausgewählten Typ verwenden
var user: UserBasicInfo = { id: 1, name: "Alice" };
console.log("Benutzer-Basisinfo: " + JSON.stringify(user));
Run result:
用户基本信息: {"id":1,"name":"Alice"}
Vergleich:Die Kombination von Pick und Partial kann einen Typ erzeugen, der nur einige optionale Eigenschaften enthält.
Omit<T, K> - Eigenschaften ausschließen
Omit schließt die angegebenen Eigenschaften K aus dem Typ T aus und gibt einen neuen Typ zurück, der aus den verbleibenden Eigenschaften besteht.
Es ist das Gegenteil von Pick und wird verwendet, um nicht benötigte Eigenschaften zu entfernen.
Beispiel
interface User {
// Benutzer-ID
id: number;
// Benutzername
name: string;
// Benutzer-E-Mail
email: string;
// Benutzerpasswort
password: string;
}
// Omit: die angegebenen Eigenschaften ausschließen
// Schließe die password-Eigenschaft von User aus
type UserWithoutPassword = Omit<User, "password">;
// Verwende den resultierenden Typ nach dem Ausschluss
var user: UserWithoutPassword = { id: 1, name: "Alice", email: "[email protected]" };
console.log("Benutzer ohne Passwort: " + JSON.stringify(user));
Run result:
无密码用户: {"id":1,"name":"Alice","email":"[email protected]"}
Tipp:Omit ist das Gegenteil von Pick. Wenn du ein paar Eigenschaften ausschließen musst, verwende Omit; wenn du ein paar Eigenschaften auswählen musst, verwende Pick.
Record<K, T> - Objekttypen erstellen
Record erstellt einen Objekttyp mit Schlüsseln vom Typ K und Werten vom Typ T.
Er wird oft verwendet, um Schlüssel-Wert-Zuordnungen, Dictionary-Typen usw. zu erstellen.
Beispiel
type Role = "admin" | "user" | "guest";
// Record: konstruiert einen Objekttyp
// Schlüssel sind vom Typ Role, Werte sind vom Typ String-Array
type RolePermissions = Record<Role, string[]>;
// Verwende Record, um eine Berechtigungszuordnung zu erstellen
var permissions: RolePermissions = {
// Admin hat alle Berechtigungen
admin: ["read", "write", "delete"],
// Regulärer Benutzer hat Lese- und Schreibberechtigungen
user: ["read", "write"],
// Gast hat nur Leseberechtigung
guest: ["read"]
};
console.log("Admin-Berechtigungen: " + permissions.admin);
console.log("Gastberechtigungen: " + permissions.guest);
Run result:
管理员权限: read,write,delete 访客权限: read
Anwendungsszenarien:Record wird häufig in Szenarien verwendet, in denen Werte schnell anhand des Schlüssels nachgeschlagen werden müssen, wie z. B. Konfigurationszuordnungen, Statuszuordnungen und Berechtigungszuordnungen.
Exclude<T, U> – Typen ausschließen
Exclude entfernt aus dem Typ T alle Typen, die dem Typ U zuweisbar sind.
Wird hauptsächlich für Union-Typen verwendet, wobei bestimmte Typmember ausgeschlossen werden.
Beispiel
type T = "a" | "b" | "c" | "d";
// Exclude: angegebene Typen aus T entfernen
// Exclude "a", "b", "c", sodass nur "d" übrig bleibt
type NonABC = Exclude<T, "a" | "b" | "c">;
// Unter Verwendung des ausgeschlossenen Typs kann nur "d" zugewiesen werden
var value: NonABC = "d";
console.log("Wert: " + value);
Ausgabe:
值: d
Erklärung:Das Prinzip von Exclude ist: Wenn ein Typ in T zu U zuweisbar ist, entferne ihn aus T.
Extract<T, U> - Typen extrahieren
Extract ist das Gegenteil von Exclude; es extrahiert aus Typ T die Typen, die zu Typ U zuweisbar sind.
Wird verwendet, um bestimmte Member aus einem Union-Typ zu filtern.
Beispiel
type T = "a" | "b" | "c" | 1 | 2 | 3;
// Extract: extrahiere angegebene Typen aus T
// Alle String-Typen extrahieren: "a", "b", "c"
type Letters = Extract<T, string>;
// Den extrahierten Typ verwenden
var letter: Letters = "a";
console.log("Buchstaben: " + letter);
Ausgabe:
字母: a
Vergleich:Extract und Exclude sind komplementär. Extract(T, U) ist äquivalent zu Exclude(T, Exclude<T, U>).
NonNullable<T> - Nullish-Werte ausschließen
NonNullable entfernt null und undefined aus Typ T.
Verwenden Sie es, um sicherzustellen, dass ein Typ keine Nullish-Werte enthält.
Beispiel
type T = string | null | undefined | number;
// NonNullable: null und undefined entfernen
// Nach der Konvertierung bleiben nur string und number übrig
type NotNull = NonNullable<T>;
// Verwende den non-nullable Typ
var value: NotNull = "hello";
value = 42;
// Das Zuweisen von null führt zu einem Fehler
// value = null; // Fehler: null kann nicht zugewiesen werden
console.log("Wert: " + value);
Erklärung:NonNullable<T> ist äquivalent zu Exclude<T, null | undefined>.
ReturnType<T> - Den Rückgabetyp ermitteln
ReturnType ermittelt den Rückgabetyp eines Funktionstyps T.
Wird oft verwendet, um den Rückgabetyp aus einer vorhandenen Funktion zu extrahieren.
Beispiel
function getUser() {
return { name: "Alice", age: 25 };
}
// Eine Funktion definieren, um die Konfiguration abzurufen
function getConfig() {
return { host: "localhost", port: 8080 };
}
// ReturnType: den Rückgabetyp der Funktion ermitteln
// Den Rückgabetyp der Funktion getUser extrahieren
type UserType = ReturnType<typeof getUser>;
// Den Rückgabetyp der Funktion getConfig extrahieren
type ConfigType = ReturnType<typeof getConfig>;
// Die extrahierten Rückgabetypen verwenden, um Objekte zu erstellen
var user: UserType = { name: "Bob", age: 30 };
var config: ConfigType = { host: "example.com", port: 3000 };
console.log("Benutzer: " + JSON.stringify(user));
console.log("Konfiguration: " + JSON.stringify(config));
Ausgabe:
User: {"name":"Bob","age":30}
配置: {"host":"example.com","port":3000}
Tipp:T in ReturnType<T> muss ein Funktionstyp sein. Du kannst typeof verwenden, um den Typ einer Funktion zu ermitteln.
Hinweise
- Utility-Typen sind alle generisch:Übergib bei ihrer Verwendung konkrete Typargumente
- Readonly und optional:Utility-Typen lassen sich kombinieren, z. B. Partial<Readonly<T>>
- Eingebaute Typen:Diese Utility-Typen sind in TypeScript integriert und erfordern keine Installation
- Benutzerdefinierte Utility-Typen:Du kannst benutzerdefinierte Utility-Typen auf Basis von Mapped Types und Conditional Types erstellen
Fortgeschritten:Wenn die eingebauten Utility-Typen deine Anforderungen nicht erfüllen, kannst du benutzerdefinierte Utility-Typen anhand des TypeScript-Quellcodes implementieren.
Zusammenfassung
TypeScript Utility-Typen sind ein wichtiger Bestandteil des Typsystems.
- Partial<T>:Alle Eigenschaften optional machen
- Required<T>:Alle Eigenschaften erforderlich machen
- Readonly<T>:Alle Eigenschaften schreibgeschützt machen
- Pick<T,K>:Angegebene Eigenschaften auswählen
- Omit<T,K>:Angegebene Eigenschaften ausschließen
- Record<K,T>:Objekttypen erstellen
- Exclude/Extract:Typfilterung
- NonNullable:null und undefined ausschließen
- ReturnType:Rückgabetyp einer Funktion ermitteln
Best Practices:Die geschickte Nutzung von Utility-Typen kann Code typsicherer machen, wiederholte Typdefinitionen reduzieren und die Wartbarkeit des Codes verbessern.
Weitere Erweiterungen