Utility Types
Lerne die eingebauten Utility Types in TypeScript für häufige Typ-Transformationen.
Utility Types
TypeScript bietet eine Reihe eingebauter Utility Types, die häufige Typ-Transformationen vereinfachen. Sie sind generische Typen, die auf bestehende Typen angewendet werden können.
Partial
Macht alle Properties optional:
type User = {
id: number;
name: string;
email: string;
};
type PartialUser = Partial<User>;
// { id?: number; name?: string; email?: string; }
// Praktisch für Updates
function updateUser(id: number, updates: Partial<User>): User {
const user = getUser(id);
return { ...user, ...updates };
}
updateUser(1, { name: "Max" }); // Nur name ändern
Required
Macht alle Properties required:
type Config = {
apiUrl?: string;
timeout?: number;
retries?: number;
};
type RequiredConfig = Required<Config>;
// { apiUrl: string; timeout: number; retries: number; }
function initialize(config: RequiredConfig): void {
// Alle Properties sind garantiert vorhanden
console.log(`API: ${config.apiUrl}, Timeout: ${config.timeout}`);
}
Readonly
Macht alle Properties readonly:
type User = {
id: number;
name: string;
};
type ReadonlyUser = Readonly<User>;
// { readonly id: number; readonly name: string; }
const user: ReadonlyUser = { id: 1, name: "Max" };
// user.name = "Anna"; // Fehler: Cannot assign to 'name'
// Praktisch für immutable State
function freeze<T>(obj: T): Readonly<T> {
return Object.freeze(obj);
}
Pick<T, K>
Wählt bestimmte Properties aus:
type User = {
id: number;
name: string;
email: string;
password: string;
createdAt: Date;
};
type PublicUser = Pick<User, "id" | "name" | "email">;
// { id: number; name: string; email: string; }
type Credentials = Pick<User, "email" | "password">;
// { email: string; password: string; }
Omit<T, K>
Schließt bestimmte Properties aus:
type User = {
id: number;
name: string;
email: string;
password: string;
};
type SafeUser = Omit<User, "password">;
// { id: number; name: string; email: string; }
type CreateUserInput = Omit<User, "id">;
// { name: string; email: string; password: string; }
// Kombiniert
type UpdateUserInput = Partial<Omit<User, "id">>;
// { name?: string; email?: string; password?: string; }
Record<K, T>
Erstellt einen Objekttyp mit bestimmten Keys:
type Role = "admin" | "user" | "guest";
type Permissions = Record<Role, string[]>;
// { admin: string[]; user: string[]; guest: string[]; }
const permissions: Permissions = {
admin: ["read", "write", "delete"],
user: ["read", "write"],
guest: ["read"]
};
// Mit komplexerem Value-Typ
type UserRecord = Record<string, User>;
const users: UserRecord = {
"user-1": { id: 1, name: "Max", email: "max@example.com", password: "..." },
"user-2": { id: 2, name: "Anna", email: "anna@example.com", password: "..." }
};
Exclude<T, U>
Entfernt Typen aus einer Union:
type AllTypes = string | number | boolean | null | undefined;
type NonNullTypes = Exclude<AllTypes, null | undefined>;
// string | number | boolean
type Primitives = Exclude<AllTypes, boolean>;
// string | number | null | undefined
// Praktisch für Event-Typen
type Events = "click" | "scroll" | "keydown" | "keyup" | "focus" | "blur";
type MouseEvents = Exclude<Events, "keydown" | "keyup" | "focus" | "blur">;
// "click" | "scroll"
Extract<T, U>
Extrahiert Typen aus einer Union:
type AllTypes = string | number | boolean | null | undefined;
type Strings = Extract<AllTypes, string>;
// string
type Nullish = Extract<AllTypes, null | undefined>;
// null | undefined
// Mit Objekttypen
type Actions =
| { type: "ADD"; payload: number }
| { type: "REMOVE"; payload: number }
| { type: "RESET" };
type AddAction = Extract<Actions, { type: "ADD" }>;
// { type: "ADD"; payload: number }
NonNullable
Entfernt null und undefined:
type MaybeString = string | null | undefined;
type DefinitelyString = NonNullable<MaybeString>;
// string
// Praktisch für Funktionsparameter
function process(value: string | null | undefined): void {
if (value !== null && value !== undefined) {
const definite: NonNullable<typeof value> = value;
console.log(definite.toUpperCase());
}
}
ReturnType
Extrahiert den Rückgabetyp einer Funktion:
function getUser() {
return {
id: 1,
name: "Max",
email: "max@example.com"
};
}
type User = ReturnType<typeof getUser>;
// { id: number; name: string; email: string; }
// Auch für Arrow Functions
const createConfig = () => ({
apiUrl: "https://api.example.com",
timeout: 5000
});
type Config = ReturnType<typeof createConfig>;
// { apiUrl: string; timeout: number; }
Parameters
Extrahiert Parameter-Typen als Tuple:
function greet(name: string, age: number): string {
return `Hello ${name}, you are ${age}`;
}
type GreetParams = Parameters<typeof greet>;
// [name: string, age: number]
// Nützlich für Wrapper-Funktionen
function logAndCall<F extends (...args: any[]) => any>(
fn: F,
...args: Parameters<F>
): ReturnType<F> {
console.log("Calling with:", args);
return fn(...args);
}
logAndCall(greet, "Max", 25); // Type-safe!
ConstructorParameters
Extrahiert Konstruktor-Parameter:
class User {
constructor(
public id: number,
public name: string,
public email: string
) {}
}
type UserParams = ConstructorParameters<typeof User>;
// [id: number, name: string, email: string]
function createUser(...args: UserParams): User {
return new User(...args);
}
createUser(1, "Max", "max@example.com");
InstanceType
Extrahiert den Instanz-Typ eines Konstruktors:
class User {
constructor(public name: string) {}
}
type UserInstance = InstanceType<typeof User>;
// User
function createInstance<T extends new (...args: any[]) => any>(
constructor: T,
...args: ConstructorParameters<T>
): InstanceType<T> {
return new constructor(...args);
}
const user = createInstance(User, "Max");
// user ist vom Typ User
ThisParameterType und OmitThisParameter
Arbeiten mit dem this Parameter:
function greet(this: { name: string }, greeting: string): string {
return `${greeting}, ${this.name}!`;
}
type ThisType = ThisParameterType<typeof greet>;
// { name: string }
type WithoutThis = OmitThisParameter<typeof greet>;
// (greeting: string) => string
Awaited
Unwraps Promise-Typen:
type A = Awaited<Promise<string>>;
// string
type B = Awaited<Promise<Promise<number>>>;
// number
type C = Awaited<boolean | Promise<string>>;
// boolean | string
// Praktisch für async Funktionen
async function fetchUser(): Promise<{ id: number; name: string }> {
return { id: 1, name: "Max" };
}
type User = Awaited<ReturnType<typeof fetchUser>>;
// { id: number; name: string }
Praktische Kombinationen
CRUD Operations
type User = {
id: number;
name: string;
email: string;
password: string;
createdAt: Date;
updatedAt: Date;
};
// Für Create - ohne id und Timestamps
type CreateUserInput = Omit<User, "id" | "createdAt" | "updatedAt">;
// Für Update - alles optional außer id
type UpdateUserInput = Partial<Omit<User, "id">> & Pick<User, "id">;
// Für Response - ohne Passwort
type UserResponse = Omit<User, "password">;
// Für Listen - nur wichtige Felder
type UserListItem = Pick<User, "id" | "name" | "email">;
Form State
type FormField<T> = {
value: T;
touched: boolean;
error: string | null;
};
type FormState<T> = {
[K in keyof T]: FormField<T[K]>;
};
type FormValues<T> = {
[K in keyof T]: T[K] extends FormField<infer V> ? V : never;
};
type User = {
name: string;
email: string;
age: number;
};
type UserFormState = FormState<User>;
type UserFormValues = FormValues<UserFormState>;
API Types
type ApiEndpoints = {
"/users": { GET: User[]; POST: CreateUserInput };
"/users/:id": { GET: User; PUT: UpdateUserInput; DELETE: void };
};
type GetEndpoints<T> = {
[K in keyof T]: T[K] extends { GET: infer R } ? R : never;
};
type PostEndpoints<T> = {
[K in keyof T]: T[K] extends { POST: infer R } ? R : never;
};
Zusammenfassung
| Utility Type | Beschreibung |
|---|---|
Partial<T> | Alle Properties optional |
Required<T> | Alle Properties required |
Readonly<T> | Alle Properties readonly |
Pick<T, K> | Bestimmte Properties wählen |
Omit<T, K> | Properties ausschließen |
Record<K, T> | Objekt mit bestimmten Keys |
Exclude<T, U> | Aus Union entfernen |
Extract<T, U> | Aus Union extrahieren |
NonNullable<T> | null/undefined entfernen |
ReturnType<T> | Rückgabetyp einer Funktion |
Parameters<T> | Parameter einer Funktion |
Awaited<T> | Promise unwrappen |
Diese Utility Types sind Bausteine für komplexere Typ-Transformationen. Kombiniere sie für mächtige, wiederverwendbare Typen!
Im nächsten Modul wenden wir alles Gelernte in praktischen Projekten an!