Warum TypeScript?
TypeScript ist JavaScript mit Typen. Das klingt simpel, verändert aber fundamental, wie Sie Code schreiben und Fehler finden.
Das Problem mit JavaScript:
function calculateTotal(items) {
return items.reduce((sum, item) => sum + item.price, 0);
}
// Funktioniert
calculateTotal([{ price: 10 }, { price: 20 }]); // 30
// Crash zur Laufzeit!
calculateTotal("not an array"); // TypeError
calculateTotal([{ cost: 10 }]); // NaN (price ist undefined)Diese Fehler finden Sie erst, wenn der Code läuft – im schlimmsten Fall in Produktion.
Die TypeScript-Lösung:
interface Item {
price: number;
}
function calculateTotal(items: Item[]): number {
return items.reduce((sum, item) => sum + item.price, 0);
}
// Fehler wird sofort angezeigt!
calculateTotal("not an array"); // Type 'string' is not assignable
calculateTotal([{ cost: 10 }]); // Property 'price' is missingDer Editor zeigt Fehler bevor Sie den Code ausführen.
Die Basics in 5 Minuten
1. Primitive Typen
// Die Grundtypen
let name: string = "Max";
let age: number = 30;
let isActive: boolean = true;
// Arrays
let numbers: number[] = [1, 2, 3];
let names: string[] = ["Anna", "Ben"];
// TypeScript inferiert oft automatisch
let city = "Stuttgart"; // TypeScript weiß: das ist ein string2. Objekte und Interfaces
// Interface definiert die Form eines Objekts
interface User {
id: number;
name: string;
email: string;
age?: number; // Optional (?)
}
const user: User = {
id: 1,
name: "Max Mustermann",
email: "max@example.com",
// age ist optional, kann weggelassen werden
};
// Funktion mit typisiertem Parameter
function greetUser(user: User): string {
return `Hallo, ${user.name}!`;
}3. Funktionen
// Parameter und Rückgabetyp
function add(a: number, b: number): number {
return a + b;
}
// Arrow Function
const multiply = (a: number, b: number): number => a * b;
// Optionale Parameter
function greet(name: string, greeting?: string): string {
return `${greeting || "Hallo"}, ${name}!`;
}
// Default-Werte
function createUser(name: string, role: string = "user"): User {
// ...
}4. Union Types
// Kann mehrere Typen haben
let id: string | number;
id = "abc123"; // OK
id = 42; // Auch OK
// Nützlich für Funktionen
function formatId(id: string | number): string {
if (typeof id === "string") {
return id.toUpperCase();
}
return id.toString();
}5. Type Aliases
// Eigene Typen definieren
type Status = "pending" | "approved" | "rejected";
interface Order {
id: number;
status: Status;
}
const order: Order = {
id: 1,
status: "pending", // Nur diese 3 Werte erlaubt
};
order.status = "invalid"; // Fehler!Praktische Patterns
API-Responses typisieren
interface ApiResponse<T> {
data: T;
status: number;
message: string;
}
interface Product {
id: number;
name: string;
price: number;
}
async function fetchProducts(): Promise<ApiResponse<Product[]>> {
const response = await fetch("/api/products");
return response.json();
}
// Nutzung - TypeScript kennt die Struktur
const result = await fetchProducts();
result.data.forEach(product => {
console.log(product.name); // Autocomplete funktioniert!
});React Components
interface ButtonProps {
label: string;
onClick: () => void;
variant?: "primary" | "secondary";
disabled?: boolean;
}
function Button({ label, onClick, variant = "primary", disabled }: ButtonProps) {
return (
<button
onClick={onClick}
disabled={disabled}
className={variant}
>
{label}
</button>
);
}
// Verwendung - Fehler werden sofort angezeigt
<Button label="Klick mich" onClick={() => {}} />
<Button label={42} /> // Fehler: number ist kein stringMigration von JavaScript
Schritt 1: Setup
npm install typescript @types/node --save-dev
npx tsc --initSchritt 2: Schrittweise migrieren
Benennen Sie Dateien von .js zu .ts (oder .tsx für React). TypeScript erlaubt anfangs any:
// Vorher (JavaScript)
function processData(data) {
return data.map(item => item.value);
}
// Zwischenschritt (TypeScript mit any)
function processData(data: any): any {
return data.map((item: any) => item.value);
}
// Endgültig (vollständig typisiert)
interface DataItem {
value: number;
}
function processData(data: DataItem[]): number[] {
return data.map(item => item.value);
}Schritt 3: Strict Mode aktivieren
In tsconfig.json:
{
"compilerOptions": {
"strict": true
}
}Häufige Stolpersteine
1. Object vs. object vs. {}
// Falsch - zu allgemein
let data: Object = { name: "Max" };
// Richtig - spezifisch
interface UserData {
name: string;
}
let data: UserData = { name: "Max" };2. Type Assertions sparsam einsetzen
// Vermeiden wenn möglich
const element = document.getElementById("app") as HTMLDivElement;
// Besser: Type Guard
const element = document.getElementById("app");
if (element instanceof HTMLDivElement) {
// Jetzt weiß TypeScript, dass es ein HTMLDivElement ist
}3. null und undefined
function getUser(id: number): User | null {
// Kann User oder null zurückgeben
}
const user = getUser(1);
console.log(user.name); // Fehler! user könnte null sein
// Richtig:
if (user) {
console.log(user.name);
}
// Oder mit Optional Chaining:
console.log(user?.name);Fazit
TypeScript ist kein Allheilmittel, aber es löst echte Probleme:
- Weniger Bugs: Viele Fehler werden beim Schreiben gefunden, nicht in Produktion
- Bessere IDE-Unterstützung: Autocomplete, Refactoring, Navigation
- Dokumentation im Code: Typen erklären, was eine Funktion erwartet
- Sichereres Refactoring: Der Compiler findet alle Stellen, die angepasst werden müssen
Der Einstieg kostet etwas Zeit, aber der ROI kommt schnell – besonders in größeren Projekten oder Teams.