← Zurück

TypeScript

Utility Types & Patterns die ich täglich nutze.

Utility Types Built-in Power

Partial<T>

Macht alle Properties optional. Perfekt für Update-Funktionen.

interface User {
  id: string;
  name: string;
  email: string;
}

// Nur die Felder die sich ändern
function updateUser(id: string, updates: Partial<User>) {
  // ...
}

updateUser('123', { name: 'Alex' }); // ✅ Valid

Pick<T, K> & Omit<T, K>

Erstellt Types mit nur bestimmten Properties (Pick) oder ohne bestimmte (Omit).

// Nur id und name
type UserPreview = Pick<User, 'id' | 'name'>;

// Alles außer id (für Create)
type CreateUserInput = Omit<User, 'id'>;

// Kombiniert: API Response
type UserListResponse = ApiResponse<Pick<User, 'id' | 'name'>[]>;

Record<K, T>

Dictionary-ähnliche Strukturen mit definierten Key- und Value-Types.

// String Keys → User Arrays
type UsersByRole = Record<string, User[]>;

// Enum Keys → spezifische Values
type StatusColors = Record<Status, string>;

const colors: StatusColors = {
  pending: '#f59e0b',
  active: '#10b981',
  error: '#ef4444',
};

Required<T> & Readonly<T>

interface Config {
  host?: string;
  port?: number;
}

// Alle Properties required
const defaults: Required<Config> = {
  host: 'localhost',
  port: 3000,
};

// Alle Properties readonly (immutable)
const frozen: Readonly<Config> = { host: 'prod' };
frozen.host = 'dev'; // ❌ Error!

Praktische Patterns

API Response Wrapper

interface ApiResponse<T> {
  data: T;
  status: number;
  message: string;
}

// Typisierte Responses
type UsersResponse = ApiResponse<User[]>;
type UserResponse = ApiResponse<User>;

async function fetchUsers(): Promise<UsersResponse> {
  // ...
}

Discriminated Unions

Type-safe State Management mit automatischem Narrowing.

type RequestState<T> =
  | { status: 'idle' }
  | { status: 'loading' }
  | { status: 'success'; data: T }
  | { status: 'error'; error: string };

function render(state: RequestState<User[]>) {
  switch (state.status) {
    case 'loading':
      return <Spinner />;
    case 'success':
      return <List data={state.data} />; // ✅ data ist hier verfügbar
    case 'error':
      return <Error msg={state.error} />;
  }
}

Type Guards

function isUser(obj: unknown): obj is User {
  return (
    typeof obj === 'object' &&
    obj !== null &&
    'id' in obj &&
    'name' in obj
  );
}

// Jetzt ist TypeScript schlau
if (isUser(data)) {
  console.log(data.name); // ✅ Kein Error
}

💡 Key Insight

Utility Types existieren nur zur Compile-Zeit. Sie haben zero runtime cost — nach dem Build ist kein TypeScript Code mehr da.