Zum Inhalt springen
TypeScript Anfänger 20 min

Type Aliases

Lerne wie du mit Type Aliases eigene Typen in TypeScript definierst und wann du sie verwendest.

Aktualisiert:

Type Aliases

Type Aliases ermöglichen es dir, eigene Typnamen zu definieren. Sie sind ein fundamentales Feature in TypeScript, das deinen Code lesbarer und wartbarer macht.

Grundlagen

// Einfacher Type Alias
type UserId = number;
type UserName = string;

let id: UserId = 123;
let name: UserName = "Max";

// Für Objekte
type User = {
    id: UserId;
    name: UserName;
    email: string;
};

const user: User = {
    id: 1,
    name: "Max",
    email: "max@example.com"
};

Type Alias vs. direkte Annotation

// Ohne Type Alias - unübersichtlich
function processUser(user: { id: number; name: string; email: string }): void {
    // ...
}

// Mit Type Alias - sauber
type User = {
    id: number;
    name: string;
    email: string;
};

function processUser(user: User): void {
    // ...
}

Arten von Type Aliases

Primitive Types

type ID = number | string;
type Age = number;
type Email = string;
type IsActive = boolean;

Object Types

type Point = {
    x: number;
    y: number;
};

type Circle = {
    center: Point;
    radius: number;
};

Union Types

type Status = "pending" | "active" | "completed" | "cancelled";
type Result = "success" | "error";
type Nullable<T> = T | null;

Intersection Types

type Timestamped = {
    createdAt: Date;
    updatedAt: Date;
};

type Identifiable = {
    id: number;
};

type Entity = Timestamped & Identifiable;

Function Types

type Callback = () => void;
type EventHandler = (event: Event) => void;
type Comparator<T> = (a: T, b: T) => number;
type AsyncFunction<T> = () => Promise<T>;

Tuple Types

type Coordinates = [number, number];
type RGB = [number, number, number];
type NameAge = [string, number];
type Response = [boolean, string, unknown?];

Generische Type Aliases

// Einfaches Generic
type Container<T> = {
    value: T;
};

const numContainer: Container<number> = { value: 42 };
const strContainer: Container<string> = { value: "hello" };

// Mit mehreren Type Parameters
type Pair<K, V> = {
    key: K;
    value: V;
};

const pair: Pair<string, number> = { key: "age", value: 25 };

// Mit Default Type
type Optional<T = string> = T | undefined;

let opt1: Optional = undefined;          // Optional<string>
let opt2: Optional<number> = undefined;  // Optional<number>

Bedingte Types

// Conditional Type
type IsString<T> = T extends string ? true : false;

type A = IsString<string>;  // true
type B = IsString<number>;  // false

// Praktischer: Extract und Exclude
type EventType = "click" | "scroll" | "keydown" | "keyup";
type KeyEvents = Extract<EventType, "keydown" | "keyup">;  // "keydown" | "keyup"
type NonKeyEvents = Exclude<EventType, "keydown" | "keyup">;  // "click" | "scroll"

Mapped Types

// Alle Properties optional machen
type Partial<T> = {
    [P in keyof T]?: T[P];
};

// Alle Properties readonly machen
type Readonly<T> = {
    readonly [P in keyof T]: T[P];
};

// Beispiel
type User = {
    id: number;
    name: string;
    email: string;
};

type PartialUser = Partial<User>;
// { id?: number; name?: string; email?: string; }

type ReadonlyUser = Readonly<User>;
// { readonly id: number; readonly name: string; readonly email: string; }

Template Literal Types

type Color = "red" | "green" | "blue";
type Size = "small" | "medium" | "large";

// Kombinieren mit Template Literals
type ColorSize = `${Color}-${Size}`;
// "red-small" | "red-medium" | "red-large" | "green-small" | ...

type EventName = `on${Capitalize<string>}`;
// Alle Strings die mit "on" beginnen und einen Großbuchstaben haben

type HttpMethod = "GET" | "POST" | "PUT" | "DELETE";
type Endpoint = `/api/${string}`;
type ApiRoute = `${HttpMethod} ${Endpoint}`;

Praktische Beispiele

API Types

type HttpStatus = 200 | 201 | 400 | 401 | 403 | 404 | 500;

type ApiResponse<T> = {
    status: HttpStatus;
    data?: T;
    error?: string;
    timestamp: number;
};

type User = { id: number; name: string };
type UserResponse = ApiResponse<User>;
type UsersResponse = ApiResponse<User[]>;

State Management

type LoadingState = {
    status: "loading";
};

type SuccessState<T> = {
    status: "success";
    data: T;
};

type ErrorState = {
    status: "error";
    error: Error;
};

type AsyncState<T> = LoadingState | SuccessState<T> | ErrorState;

// Verwendung
type UserState = AsyncState<User>;

function renderUserState(state: UserState): string {
    switch (state.status) {
        case "loading":
            return "Loading...";
        case "success":
            return `User: ${state.data.name}`;
        case "error":
            return `Error: ${state.error.message}`;
    }
}

Form Handling

type InputType = "text" | "email" | "password" | "number";

type ValidationRule = {
    required?: boolean;
    minLength?: number;
    maxLength?: number;
    pattern?: RegExp;
    custom?: (value: string) => boolean;
};

type FormField<T extends InputType> = {
    type: T;
    name: string;
    label: string;
    placeholder?: string;
    validation?: ValidationRule;
    defaultValue?: T extends "number" ? number : string;
};

type TextField = FormField<"text">;
type EmailField = FormField<"email">;
type NumberField = FormField<"number">;

Event System

type EventMap = {
    click: { x: number; y: number };
    keydown: { key: string; code: number };
    scroll: { scrollTop: number; scrollLeft: number };
};

type EventName = keyof EventMap;
type EventData<E extends EventName> = EventMap[E];

type EventHandler<E extends EventName> = (data: EventData<E>) => void;

type EventListeners = {
    [E in EventName]?: EventHandler<E>[];
};

Utility Pattern

// Null-safe Type
type Maybe<T> = T | null | undefined;

// Deep Readonly
type DeepReadonly<T> = {
    readonly [P in keyof T]: T[P] extends object ? DeepReadonly<T[P]> : T[P];
};

// Non-nullable
type NonNullable<T> = T extends null | undefined ? never : T;

// Record shorthand
type StringRecord = Record<string, string>;
type NumberRecord = Record<string, number>;

// Function helpers
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;

Zusammenfassung

Type Aliases können:

  • Primitive Typen benennen
  • Objekt-Shapes definieren
  • Union und Intersection Types erstellen
  • Funktionstypen beschreiben
  • Mit Generics arbeiten
  • Bedingte Logik enthalten

Best Practices:

  • Verwende sprechende Namen
  • Halte Types fokussiert
  • Nutze Generics für Wiederverwendbarkeit
  • Exportiere Types für Sharing

Im nächsten Kapitel lernst du die Unterschiede zwischen Interface und Type!

Zurück zum TypeScript Kurs