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.


Background Title TypeScript Utility Types Primitive Types Primitive Types interface User { id: number; name: string; email: string; } Arrow Utility Types Utility Types Partial<T> - All Optional Required<T> - All Required Readonly<T> - All Readonly Pick<T,K> - Select Properties Omit<T,K> - Exclude Properties Arrow Result Result Type type Result = { id?: number; name?: string; email?: string; } Lower Part Common Utility Types First Row Partial<T> All properties optional { a?: T } Required<T> All properties required { -? } Readonly<T> All properties readonly { readonly } Pick<T,K> Select specified properties { pick } Second Row (Fix Focus) Record<K,T> Construct Object Types Omit<T,K> Exclude Specified Properties Arrow Definition

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

// Definieren Sie ein Benutzer-Interface mit erforderlichen Eigenschaften
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

// Definieren Sie ein Konfigurations-Interface, bei dem alle Eigenschaften optional sind
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

// Ein User-Interface definieren
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

// Vollständige Benutzeroberfläche definieren
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

// Vollständige Benutzeroberfläche definieren
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

// Definiere einen Rollentyp
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

// Definiere einen Union-Typ, der a, b, c, d enthält
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

// Definiere einen gemischten Union-Typ, der Strings und Zahlen enthält
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

// Definiere einen gemischten Typ, der Strings, null, undefined und Zahlen enthält
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

// Eine Funktion definieren, um einen Benutzer abzurufen
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