TypeScript Utility Types - Eingebaute Type Helpers
TypeScript bietet viele eingebaute Utility Types zum Transformieren von Types.
Partial<T>
Macht alle Properties optional:
interface User {
name: string
age: number
email: string
}
type PartialUser = Partial<User>
// { name?: string; age?: number; email?: string }
function updateUser(user: User, updates: Partial<User>): User {
return { ...user, ...updates }
}
const user: User = {
name: "Max",
age: 25,
email: "max@test.com"
}
updateUser(user, { age: 26 }) // ✅ Nur age updaten
Required<T>
Macht alle Properties required:
interface User {
name?: string
age?: number
email?: string
}
type RequiredUser = Required<User>
// { name: string; age: number; email: string }
const user: RequiredUser = {
name: "Max",
age: 25,
email: "max@test.com"
}
Readonly<T>
Macht alle Properties readonly:
interface User {
name: string
age: number
}
type ReadonlyUser = Readonly<User>
// { readonly name: string; readonly age: number }
const user: ReadonlyUser = {
name: "Max",
age: 25
}
user.age = 26 // ❌ Error: readonly
Häufige Verwendung:
function freeze<T>(obj: T): Readonly<T> {
return Object.freeze(obj)
}
const user = freeze({ name: "Max", age: 25 })
user.age = 26 // ❌ Error
Pick<T, K>
Wählt bestimmte Properties aus:
interface User {
id: number
name: string
email: string
password: string
createdAt: Date
}
type PublicUser = Pick<User, "id" | "name" | "email">
// { id: number; name: string; email: string }
function getPublicUser(user: User): PublicUser {
return {
id: user.id,
name: user.name,
email: user.email
}
}
Omit<T, K>
Entfernt bestimmte Properties:
interface User {
id: number
name: string
email: string
password: string
}
type UserWithoutPassword = Omit<User, "password">
// { id: number; name: string; email: string }
type UserWithoutSensitive = Omit<User, "password" | "email">
// { id: number; name: string }
Verwendung bei Formularen:
interface Product {
id: number
name: string
price: number
createdAt: Date
updatedAt: Date
}
type ProductFormData = Omit<Product, "id" | "createdAt" | "updatedAt">
// { name: string; price: number }
Record<K, T>
Erstellt ein Object Type mit spezifischen Keys und Werten:
type Roles = "admin" | "user" | "guest"
type Permissions = Record<Roles, string[]>
// { admin: string[]; user: string[]; guest: string[] }
const permissions: Permissions = {
admin: ["read", "write", "delete"],
user: ["read", "write"],
guest: ["read"]
}
Für Dictionaries:
type Dictionary = Record<string, string>
const translations: Dictionary = {
hello: "Hallo",
goodbye: "Auf Wiedersehen",
thanks: "Danke"
}
Exclude<T, U>
Entfernt Types aus Union:
type Status = "active" | "inactive" | "pending" | "deleted"
type ActiveStatus = Exclude<Status, "deleted" | "inactive">
// "active" | "pending"
function setActiveStatus(status: ActiveStatus): void {
console.log(status)
}
setActiveStatus("active") // ✅ OK
setActiveStatus("deleted") // ❌ Error
Extract<T, U>
Extrahiert Types aus Union:
type Status = "active" | "inactive" | "pending" | "deleted"
type InactiveStatus = Extract<Status, "inactive" | "deleted">
// "inactive" | "deleted"
NonNullable<T>
Entfernt null und undefined:
type MaybeString = string | null | undefined
type DefiniteString = NonNullable<MaybeString>
// string
function process(value: MaybeString): NonNullable<MaybeString> {
if (value === null || value === undefined) {
return "default"
}
return value
}
ReturnType<T>
Extrahiert Return Type einer Funktion:
function createUser() {
return {
id: 1,
name: "Max",
email: "max@test.com"
}
}
type User = ReturnType<typeof createUser>
// { id: number; name: string; email: string }
const user: User = {
id: 2,
name: "Anna",
email: "anna@test.com"
}
Parameters<T>
Extrahiert Parameter Types:
function updateUser(id: number, name: string, age: number) {
// ...
}
type UpdateUserParams = Parameters<typeof updateUser>
// [number, string, number]
function callUpdate(...args: UpdateUserParams) {
updateUser(...args)
}
Awaited<T>
Unwrapped Promise Type:
type A = Awaited<Promise<string>> // string
type B = Awaited<Promise<Promise<number>>> // number
async function fetchData(): Promise<{ name: string }> {
return { name: "Data" }
}
type Data = Awaited<ReturnType<typeof fetchData>>
// { name: string }
Kombinationen
Utility Types kombinieren:
interface User {
id: number
name: string
email: string
password: string
role: "admin" | "user"
createdAt: Date
}
// Partial + Pick
type UpdateUserData = Partial<Pick<User, "name" | "email" | "role">>
// { name?: string; email?: string; role?: "admin" | "user" }
// Omit + Readonly
type SafeUser = Readonly<Omit<User, "password">>
// { readonly id: number; readonly name: string; ... }
// Required + Pick
type LoginData = Required<Pick<User, "email" | "password">>
// { email: string; password: string }
interface Product {
id: number
name: string
description: string
price: number
stock: number
categoryId: number
createdAt: Date
updatedAt: Date
}
// CREATE - ohne id und timestamps
type CreateProductDto = Omit<Product, "id" | "createdAt" | "updatedAt">
// UPDATE - alles optional außer id
type UpdateProductDto = Partial<CreateProductDto> & Pick<Product, "id">
// READ - public view ohne sensitive data
type ProductView = Omit<Product, "stock"> & {
inStock: boolean
}
// LIST Response
type ProductListResponse = {
products: ProductView[]
total: number
page: number
}
// Usage
function createProduct(data: CreateProductDto): Promise<Product> {
// ...
}
function updateProduct(data: UpdateProductDto): Promise<Product> {
// ...
}
function getProduct(id: number): Promise<ProductView> {
// ...
}📝 Quiz
Was macht Partial<T>?
Tipps & Tricks
Eigene Utility Types
// DeepPartial - auch nested Properties optional
type DeepPartial<T> = {
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K]
}
interface User {
name: string
address: {
street: string
city: string
}
}
type PartialUser = DeepPartial<User>
// { name?: string; address?: { street?: string; city?: string } }
Utility Types mit Generics
type AsyncReturnType<T extends (...args: any) => Promise<any>> =
T extends (...args: any) => Promise<infer R> ? R : any
async function fetchUser() {
return { name: "Max", age: 25 }
}
type User = AsyncReturnType<typeof fetchUser>
// { name: string; age: number }
Utility Types chaining
type A = Readonly<Required<Partial<User>>>
// Erst Partial, dann Required (= original), dann Readonly
Häufige Fehler
Fehler 1: Pick/Omit mit falschen Keys
❌ FALSCH:
interface User {
name: string
age: number
}
type PickedUser = Pick<User, "email"> // ❌ Error: 'email' existiert nicht
✅ RICHTIG:
type PickedUser = Pick<User, "name" | "age">
Fehler 2: Record mit falschen Key Types
❌ FALSCH:
// Key Type muss string | number | symbol sein
type Invalid = Record<boolean, string> // ❌ Error
✅ RICHTIG:
type Valid = Record<string, string>
type Valid2 = Record<"a" | "b" | "c", number>
Fehler 3: Readonly vs Readonly Array verwechseln
❌ FALSCH:
const user: Readonly<{ hobbies: string[] }> = {
hobbies: ["gaming"]
}
user.hobbies.push("coding") // ✅ Funktioniert! (Array änderbar)
✅ RICHTIG:
const user: Readonly<{ hobbies: readonly string[] }> = {
hobbies: ["gaming"]
}
user.hobbies.push("coding") // ❌ Error
Zusammenfassung
Du hast gelernt:
- ✅ Partial<T> - Alle Properties optional
- ✅ Required<T> - Alle Properties required
- ✅ Readonly<T> - Alle Properties readonly
- ✅ Pick<T, K> - Bestimmte Properties auswählen
- ✅ Omit<T, K> - Bestimmte Properties entfernen
- ✅ Record<K, T> - Object Type erstellen
- ✅ ReturnType<T> - Return Type extrahieren
- ✅ Utility Types kombinieren
Key Takeaways:
- Utility Types reduzieren Boilerplate Code
- Kombinationen für komplexe Types
- Pick/Omit für DTO Patterns
- ReturnType für Type Inference
- Eigene Utility Types erstellen
Nächste Schritte
Als Nächstes lernst du:
- Mapped Types
- Conditional Types
- Template Literal Types
- TypeScript mit React
Viel Erfolg! 🚀
Gut gemacht! 🎉
Du hast "TypeScript Utility Types - Eingebaute Type Helpers" abgeschlossen
Artikel bewerten
Bitte einloggen um zu bewerten
Das könnte dich auch interessieren
TypeScript Generics - Wiederverwendbare Typen
Lerne Generics in TypeScript - das Werkzeug für flexible und wiederverwendbare Komponenten, Funktionen und Classes.
TypeScript Basic Types - Primitive Datentypen
Lerne die grundlegenden Datentypen in TypeScript kennen: string, number, boolean, arrays, tuples und mehr.
TypeScript Best Practices - Professioneller Code
Lerne die wichtigsten Best Practices für sauberen und wartbaren TypeScript Code. Naming, Patterns, Do's and Don'ts.