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
anyals Parameter- oder Rückgabetyp
Im nächsten Kapitel lernst du optionale Parameter und Standardwerte!