Zum Inhalt springen
TypeScript Anfänger 25 min

Funktions-Typen in TypeScript

Lerne wie du Funktionen in TypeScript typisierst - Parameter, Rückgabewerte und Funktionstypen.

Aktualisiert:

Funktions-Typen in TypeScript

Funktionen sind das Herzstück jeder JavaScript-Anwendung. TypeScript ermöglicht es dir, Funktionen präzise zu typisieren und so viele Fehler zur Entwicklungszeit zu finden.

Grundlegende Funktions-Typisierung

Parameter typisieren

function greet(name: string): void {
    console.log(`Hallo, ${name}!`);
}

greet("Max");      // OK
greet(42);         // Fehler: Argument of type 'number'...

Rückgabewert typisieren

function add(a: number, b: number): number {
    return a + b;
}

const result = add(5, 3);  // result ist automatisch 'number'

// Fehler bei falschem Rückgabewert
function broken(x: number): number {
    return "Hallo";  // Fehler: Type 'string' is not assignable to type 'number'
}

Rückgabetypen

void

Für Funktionen ohne Rückgabewert:

function log(message: string): void {
    console.log(message);
    // Kein return oder return ohne Wert
}

undefined

Explizit undefined zurückgeben:

function findUser(id: number): string | undefined {
    if (id === 1) return "Max";
    return undefined;
}

never

Für Funktionen, die niemals zurückkehren:

// Wirft immer einen Fehler
function throwError(message: string): never {
    throw new Error(message);
}

// Endlosschleife
function infiniteLoop(): never {
    while (true) {
        // ...
    }
}

Arrow Functions typisieren

// Volle Syntax
const multiply = (a: number, b: number): number => {
    return a * b;
};

// Kurzform
const square = (n: number): number => n * n;

// Type Inference bei Arrow Functions
const double = (n: number) => n * 2;  // Rückgabetyp wird erkannt

Funktionstypen als Type Alias

Du kannst Funktionstypen als eigene Typen definieren:

// Funktionstyp definieren
type Calculator = (a: number, b: number) => number;

// Funktionen vom Typ Calculator
const add: Calculator = (a, b) => a + b;
const subtract: Calculator = (a, b) => a - b;
const multiply: Calculator = (a, b) => a * b;

// In Arrays oder Objekten verwenden
const operations: Calculator[] = [add, subtract, multiply];

Komplexere Funktionstypen

type EventHandler = (event: Event, data: unknown) => void;

type AsyncOperation<T> = () => Promise<T>;

type Validator = (value: string) => boolean | string;

Funktionen als Parameter

// Callback-Funktion als Parameter
function processData(data: number[], callback: (item: number) => void): void {
    data.forEach(callback);
}

processData([1, 2, 3], (num) => {
    console.log(num * 2);
});

// Mit Funktionstyp
type Callback = (item: number) => void;

function processData2(data: number[], callback: Callback): void {
    data.forEach(callback);
}

Funktionen als Rückgabewert

// Funktion, die eine Funktion zurückgibt
function createMultiplier(factor: number): (n: number) => number {
    return (n) => n * factor;
}

const double = createMultiplier(2);
const triple = createMultiplier(3);

console.log(double(5));  // 10
console.log(triple(5));  // 15

Call Signatures in Object Types

// Objekt mit Funktion
type Greeter = {
    message: string;
    greet(name: string): string;
};

const greeter: Greeter = {
    message: "Hallo",
    greet(name) {
        return `${this.message}, ${name}!`;
    }
};

// Call Signature für aufrufbare Objekte
type CallableGreeter = {
    (name: string): string;
    language: string;
};

const greetFn: CallableGreeter = Object.assign(
    (name: string) => `Hello, ${name}!`,
    { language: "en" }
);

console.log(greetFn("Max"));       // "Hello, Max!"
console.log(greetFn.language);     // "en"

Rest Parameters

// Rest Parameter typisieren
function sum(...numbers: number[]): number {
    return numbers.reduce((total, n) => total + n, 0);
}

sum(1, 2, 3);           // 6
sum(1, 2, 3, 4, 5);     // 15

// Mit anderen Parametern kombiniert
function logAll(prefix: string, ...messages: string[]): void {
    messages.forEach(msg => console.log(`${prefix}: ${msg}`));
}

logAll("INFO", "Start", "Processing", "Done");

Destrukturierung in Parametern

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

// Objekt-Destrukturierung
function printPoint({ x, y }: Point): void {
    console.log(`(${x}, ${y})`);
}

printPoint({ x: 10, y: 20 });

// Array-Destrukturierung
function processCoords([x, y]: [number, number]): number {
    return x + y;
}

processCoords([5, 10]);  // 15

this Parameter

TypeScript erlaubt die Typisierung von this:

type Context = {
    name: string;
    greet(this: Context): string;
};

const obj: Context = {
    name: "Max",
    greet() {
        return `Hallo, ${this.name}!`;
    }
};

obj.greet();  // "Hallo, Max!"

// Fehler wenn mit falschem this aufgerufen
const fn = obj.greet;
fn();  // Fehler: 'this' context of type 'void'...

Praktische Beispiele

Event Handler System

type EventHandler<T> = (data: T) => void;

type Events = {
    click: { x: number; y: number };
    input: { value: string };
    submit: { formData: Record<string, string> };
};

class EventEmitter {
    private handlers: Map<string, Function[]> = new Map();

    on<K extends keyof Events>(
        event: K,
        handler: EventHandler<Events[K]>
    ): void {
        const existing = this.handlers.get(event) || [];
        this.handlers.set(event, [...existing, handler]);
    }

    emit<K extends keyof Events>(event: K, data: Events[K]): void {
        const handlers = this.handlers.get(event) || [];
        handlers.forEach(h => h(data));
    }
}

const emitter = new EventEmitter();
emitter.on("click", ({ x, y }) => console.log(`Click at ${x}, ${y}`));
emitter.emit("click", { x: 100, y: 200 });

Middleware Pattern

type Request = { url: string; body?: unknown };
type Response = { status: number; data?: unknown };
type Next = () => void;

type Middleware = (req: Request, res: Response, next: Next) => void;

function createApp() {
    const middlewares: Middleware[] = [];

    return {
        use(middleware: Middleware): void {
            middlewares.push(middleware);
        },
        handle(req: Request): Response {
            const res: Response = { status: 200 };
            let index = 0;

            function next(): void {
                if (index < middlewares.length) {
                    middlewares[index++](req, res, next);
                }
            }

            next();
            return res;
        }
    };
}

Zusammenfassung

  • Parameter: Nach Parametername mit : type
  • Rückgabewert: Nach Parameterliste mit : type
  • void: Kein Rückgabewert
  • never: Funktion kehrt nie zurück
  • Type Aliases: Wiederverwendbare Funktionstypen
  • Rest Parameters: ...args: type[]
  • this Parameter: Explizite this-Typisierung

Best Practices:

  • Typisiere immer Parameter
  • Lass Rückgabetypen inferieren wenn möglich
  • Nutze Type Aliases für komplexe Funktionstypen
  • Vermeide any als Parameter- oder Rückgabetyp

Im nächsten Kapitel lernst du optionale Parameter und Standardwerte!

Zurück zum TypeScript Kurs