Fortgeschritten132025-01-15

TypeScript Utility Types - Eingebaute Type Helpers

Lerne die wichtigsten eingebauten Utility Types: Partial, Required, Pick, Omit, Record und mehr.

#typescript#utility-types#advanced#helpers

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 }
Real-World CRUD API Types
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! 🚀

TypeScriptLektion 8 von 15
53% abgeschlossen
Lektion abgeschlossen!

Gut gemacht! 🎉

Du hast "TypeScript Utility Types - Eingebaute Type Helpers" abgeschlossen

Artikel bewerten

0.0 (0 Bewertungen)

Bitte einloggen um zu bewerten