Zum Inhalt springen
TypeScript Anfänger 20 min

Optionale Parameter & Standardwerte

Lerne wie du optionale Parameter und Standardwerte in TypeScript-Funktionen verwendest.

Aktualisiert:

Optionale Parameter & Standardwerte

Nicht jede Funktion braucht alle Parameter bei jedem Aufruf. TypeScript bietet optionale Parameter und Standardwerte für flexible Funktionssignaturen.

Optionale Parameter

Markiere Parameter mit ? als optional:

function greet(name: string, greeting?: string): string {
    if (greeting) {
        return `${greeting}, ${name}!`;
    }
    return `Hallo, ${name}!`;
}

greet("Max");           // "Hallo, Max!"
greet("Max", "Hi");     // "Hi, Max!"

Reihenfolge beachten

Optionale Parameter müssen nach required Parametern kommen:

// OK
function example(required: string, optional?: number): void {}

// Fehler!
function wrong(optional?: string, required: number): void {}

Optionale Parameter sind undefined

function log(message: string, prefix?: string): void {
    // prefix ist string | undefined
    console.log(prefix ? `[${prefix}] ${message}` : message);
}

// Oder mit nullish coalescing
function log2(message: string, prefix?: string): void {
    const p = prefix ?? "LOG";
    console.log(`[${p}] ${message}`);
}

Standardwerte (Default Parameters)

Standardwerte machen Parameter optional und geben einen Fallback:

function greet(name: string, greeting: string = "Hallo"): string {
    return `${greeting}, ${name}!`;
}

greet("Max");           // "Hallo, Max!"
greet("Max", "Hi");     // "Hi, Max!"

Vorteile gegenüber optionalen Parametern

// Mit optionalem Parameter
function process1(data: string, count?: number): void {
    const c = count ?? 1;  // Manueller Fallback nötig
    // ...
}

// Mit Standardwert - sauberer!
function process2(data: string, count: number = 1): void {
    // count ist immer number, nie undefined
    // ...
}

Standardwerte können Ausdrücke sein

// Funktion als Standardwert
function createId(): string {
    return Math.random().toString(36).slice(2);
}

function createUser(name: string, id: string = createId()): void {
    console.log(`User ${name} mit ID ${id}`);
}

createUser("Max");              // Neue zufällige ID
createUser("Anna", "custom-1"); // Eigene ID

Mit Objekten

type Options = {
    timeout: number;
    retries: number;
    verbose: boolean;
};

function fetchData(
    url: string,
    options: Options = { timeout: 5000, retries: 3, verbose: false }
): void {
    console.log(`Fetching ${url} with timeout ${options.timeout}`);
}

fetchData("https://api.example.com");
fetchData("https://api.example.com", { timeout: 10000, retries: 5, verbose: true });

Destrukturierung mit Standardwerten

Kombiniere Destrukturierung mit Standardwerten:

type Config = {
    host?: string;
    port?: number;
    secure?: boolean;
};

function connect({
    host = "localhost",
    port = 3000,
    secure = false
}: Config = {}): void {
    const protocol = secure ? "https" : "http";
    console.log(`Connecting to ${protocol}://${host}:${port}`);
}

connect();                          // http://localhost:3000
connect({ port: 8080 });            // http://localhost:8080
connect({ host: "api.com", secure: true }); // https://api.com:3000

Komplexere Beispiele

type RequestOptions = {
    method?: "GET" | "POST" | "PUT" | "DELETE";
    headers?: Record<string, string>;
    body?: unknown;
    timeout?: number;
};

async function request(
    url: string,
    {
        method = "GET",
        headers = {},
        body = undefined,
        timeout = 5000
    }: RequestOptions = {}
): Promise<Response> {
    // TypeScript weiß: method ist immer ein String, nie undefined
    console.log(`${method} ${url}`);
    // Implementierung...
    return fetch(url, { method, headers, body: JSON.stringify(body) });
}

// Verschiedene Aufrufe
request("/api/users");
request("/api/users", { method: "POST", body: { name: "Max" } });
request("/api/data", { timeout: 10000 });

undefined vs ausgelassen

Bei Standardwerten gibt es einen wichtigen Unterschied:

function greet(name: string = "Gast"): string {
    return `Hallo, ${name}!`;
}

greet();            // "Hallo, Gast!" - Parameter ausgelassen
greet(undefined);   // "Hallo, Gast!" - undefined triggert Standardwert
greet("Max");       // "Hallo, Max!"

Bei optionalen Parametern:

function log(message: string, level?: string): void {
    console.log(level ? `[${level}]` : "", message);
}

log("Test");            // Parameter ausgelassen - level ist undefined
log("Test", undefined); // Explizit undefined - gleiches Ergebnis
log("Test", "INFO");    // "[INFO] Test"

Praktische Muster

Builder Pattern

type ButtonConfig = {
    text: string;
    variant?: "primary" | "secondary" | "danger";
    size?: "small" | "medium" | "large";
    disabled?: boolean;
    onClick?: () => void;
};

function createButton({
    text,
    variant = "primary",
    size = "medium",
    disabled = false,
    onClick = () => {}
}: ButtonConfig): HTMLButtonElement {
    const button = document.createElement("button");
    button.textContent = text;
    button.className = `btn btn-${variant} btn-${size}`;
    button.disabled = disabled;
    button.addEventListener("click", onClick);
    return button;
}

// Nur erforderliche Properties angeben
createButton({ text: "Klick mich" });

// Mit Anpassungen
createButton({
    text: "Löschen",
    variant: "danger",
    onClick: () => console.log("Gelöscht!")
});

API Client

type ApiConfig = {
    baseUrl: string;
    timeout?: number;
    headers?: Record<string, string>;
};

function createApiClient({
    baseUrl,
    timeout = 10000,
    headers = { "Content-Type": "application/json" }
}: ApiConfig) {
    return {
        async get(endpoint: string) {
            const response = await fetch(`${baseUrl}${endpoint}`, {
                headers,
                signal: AbortSignal.timeout(timeout)
            });
            return response.json();
        },

        async post(endpoint: string, data: unknown) {
            const response = await fetch(`${baseUrl}${endpoint}`, {
                method: "POST",
                headers,
                body: JSON.stringify(data),
                signal: AbortSignal.timeout(timeout)
            });
            return response.json();
        }
    };
}

const api = createApiClient({ baseUrl: "https://api.example.com" });

Logger mit Optionen

type LogLevel = "debug" | "info" | "warn" | "error";

type LoggerConfig = {
    prefix?: string;
    minLevel?: LogLevel;
    timestamp?: boolean;
};

function createLogger({
    prefix = "App",
    minLevel = "info",
    timestamp = true
}: LoggerConfig = {}) {
    const levels: LogLevel[] = ["debug", "info", "warn", "error"];

    function shouldLog(level: LogLevel): boolean {
        return levels.indexOf(level) >= levels.indexOf(minLevel);
    }

    function formatMessage(level: LogLevel, message: string): string {
        const parts: string[] = [];
        if (timestamp) parts.push(new Date().toISOString());
        parts.push(`[${prefix}]`);
        parts.push(`[${level.toUpperCase()}]`);
        parts.push(message);
        return parts.join(" ");
    }

    return {
        debug: (msg: string) => shouldLog("debug") && console.log(formatMessage("debug", msg)),
        info: (msg: string) => shouldLog("info") && console.log(formatMessage("info", msg)),
        warn: (msg: string) => shouldLog("warn") && console.warn(formatMessage("warn", msg)),
        error: (msg: string) => shouldLog("error") && console.error(formatMessage("error", msg))
    };
}

const logger = createLogger();
const debugLogger = createLogger({ minLevel: "debug", prefix: "Debug" });

Zusammenfassung

Optionale Parameter (?):

  • Typ wird zu T | undefined
  • Müssen nach required Parametern kommen
  • Benötigen manuelle Fallback-Logik

Standardwerte (= value):

  • Machen Parameter automatisch optional
  • Kein undefined im Typ
  • Können Ausdrücke oder Funktionsaufrufe sein

Best Practices:

  • Bevorzuge Standardwerte über optionale Parameter
  • Nutze Destrukturierung für Konfigurationsobjekte
  • Halte Standardwerte einfach und vorhersehbar

Im nächsten Kapitel lernst du Function Overloads!

Zurück zum TypeScript Kurs