Einleitung
TypeScript ist 2026 der Standard fuer professionelle JavaScript-Entwicklung. Ueber 90% aller neuen React-, Node.js- und Next.js-Projekte nutzen TypeScript. Und das aus gutem Grund: TypeScript findet Fehler bevor dein Code laeuft.
In diesem Tutorial lernst du TypeScript von Grund auf – mit vielen praktischen Beispielen.
Inhaltsverzeichnis
- Was ist TypeScript?
- Setup & Installation
- Grundtypen
- Interfaces & Type Aliases
- Funktionen typisieren
- Generics
- Union Types & Literal Types
- Utility Types
- TypeScript mit React
- Best Practices
1. Was ist TypeScript?
Vor allem für den praktischen Einsatz sind diese Informationen wertvoll.
TypeScript ist JavaScript mit Typen. Es wird von Microsoft entwickelt und zu normalem JavaScript kompiliert. Die Vorteile:
- Fehler frueh erkennen: Type-Checker findet Bugs beim Schreiben, nicht zur Laufzeit
- Bessere IDE-Unterstuetzung: Ferner autovervollstaendigung, Refactoring, Go-to-Definition
- Selbstdokumentierend: Ebenso typen sind lebende Dokumentation
- Sicheres Refactoring: Aenderungen propagieren sich durch die ganze Codebasis
- Ecosystem: Alle grossen Libraries haben TypeScript-Typen
// JavaScript – Fehler erst zur Laufzeit
function addiere(a, b) {
return a + b;
}
addiere("5", 3); // "53" – kein Fehler, aber falsch!
// TypeScript – Fehler SOFORT im Editor
function addiere(a: number, b: number): number {
return a + b;
}
addiere("5", 3); // ❌ Fehler: Argument of type 'string' is not assignable
Weiterhin ist es ratsam, die Ergebnisse immer kritisch zu prüfen.
2. Setup & Installation
Folglich profitierst du von einem besseren Verständnis dieser Konzepte.
# TypeScript global installieren
npm install -g typescript
# Version pruefen
tsc --version
# Neues Projekt erstellen
mkdir mein-ts-projekt
cd mein-ts-projekt
npm init -y
npm install typescript --save-dev
# tsconfig.json erstellen
npx tsc --init
Natürlich solltest du den generierten Code vor dem Einsatz testen.
tsconfig.json (empfohlene Einstellungen)
Zusammenfassend lässt sich sagen, dass dies ein zentraler Aspekt ist.
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"outDir": "./dist",
"rootDir": "./src",
"declaration": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
Deshalb empfiehlt es sich, den Prompt schrittweise zu verfeinern.
# Kompilieren und ausfuehren
npx tsc # Kompiliert alle .ts Dateien
node dist/index.js # Ausfuehren
# Oder mit ts-node (direkt ausfuehren)
npm install -D ts-node
npx ts-node src/index.ts
3. Grundtypen
Deshalb lohnt es sich, dieses Thema genauer zu betrachten.
// Primitive Typen
let name: string = "Metin";
let alter: number = 30;
let istEntwickler: boolean = true;
let nichts: null = null;
let unbestimmt: undefined = undefined;
// Arrays
let sprachen: string[] = ["TypeScript", "Python", "Go"];
let zahlen: number[] = [1, 2, 3];
let gemischt: (string | number)[] = ["text", 42];
// Tuple (feste Laenge und Typen)
let person: [string, number] = ["Metin", 30];
// Enum
enum Rolle {
Admin = "ADMIN",
User = "USER",
Gast = "GAST"
}
let meineRolle: Rolle = Rolle.Admin;
// Any (Vorsicht! Deaktiviert Type-Checking)
let dynamisch: any = "text";
dynamisch = 42; // Kein Fehler – aber das ist der Sinn von TS verloren
// Unknown (sichere Alternative zu any)
let eingabe: unknown = "text";
if (typeof eingabe === "string") {
console.log(eingabe.toUpperCase()); // Nur nach Type-Check erlaubt
}
Dementsprechend ist eine manuelle Überprüfung empfehlenswert.
4. Interfaces & Type Aliases
Natürlich gibt es dabei verschiedene Herangehensweisen.
// Interface – beschreibt die Form eines Objekts
interface User {
id: number;
name: string;
email: string;
alter?: number; // Optional (?)
readonly erstelltAm: Date; // Nur lesbar
}
const user: User = {
id: 1,
name: "Metin",
email: "metin@example.de",
erstelltAm: new Date()
};
// Type Alias
type ID = string | number;
type Produkt = {
id: ID;
name: string;
preis: number;
kategorien: string[];
};
// Interface Extension (Vererbung)
interface Admin extends User {
berechtigungen: string[];
superAdmin: boolean;
}
const admin: Admin = {
id: 1,
name: "Metin",
email: "metin@example.de",
erstelltAm: new Date(),
berechtigungen: ["users.manage", "posts.delete"],
superAdmin: true
};
// Intersection Types
type MitTimestamp = {
erstelltAm: Date;
aktualisiertAm: Date;
};
type Artikel = Produkt & MitTimestamp;
Tatsächlich lässt sich dieser Code direkt in dein Projekt übernehmen.
5. Funktionen typisieren
Ebenfalls relevant sind die praktischen Anwendungsbeispiele.
// Grundlegende Funktion mit Typen
function addiere(a: number, b: number): number {
return a + b;
}
// Arrow Function
const multipliziere = (a: number, b: number): number => a * b;
// Optional und Default Parameter
function begruessung(name: string, titel?: string): string {
return titel ? `${titel} ${name}` : `Hallo ${name}`;
}
function berechneRabatt(preis: number, rabatt: number = 10): number {
return preis * (1 - rabatt / 100);
}
// Rest Parameter
function summe(...zahlen: number[]): number {
return zahlen.reduce((acc, z) => acc + z, 0);
}
// Function Overloads
function formatiere(wert: string): string;
function formatiere(wert: number): string;
function formatiere(wert: string | number): string {
if (typeof wert === "string") return wert.trim();
return wert.toFixed(2);
}
// Callback-Typen
function fetchDaten(
url: string,
callback: (daten: unknown, fehler?: Error) => void
): void {
// ...
}
Grundsätzlich kannst du diesen Prompt an deine Bedürfnisse anpassen.
6. Generics
Weiterhin ist es wichtig, die Grundlagen zu verstehen.
Generics machen deinen Code wiederverwendbar und trotzdem typsicher:
// Ohne Generics – unflexibel
function erstesElement(arr: number[]): number {
return arr[0];
}
// Mit Generics – funktioniert mit jedem Typ
function erstesElement<T>(arr: T[]): T | undefined {
return arr[0];
}
erstesElement([1, 2, 3]); // Typ: number
erstesElement(["a", "b"]); // Typ: string
// Generisches Interface
interface ApiResponse<T> {
data: T;
status: number;
message: string;
}
const userResponse: ApiResponse<User> = {
data: { id: 1, name: "Metin", email: "m@x.de", erstelltAm: new Date() },
status: 200,
message: "OK"
};
// Generic Constraints
interface MitId {
id: number;
}
function findeById<T extends MitId>(items: T[], id: number): T | undefined {
return items.find(item => item.id === id);
}
// Generic Class
class Speicher<T> {
private items: T[] = [];
hinzufuegen(item: T): void { this.items.push(item); }
alle(): T[] { return [...this.items]; }
anzahl(): number { return this.items.length; }
}
7. Union Types & Literal Types
Außerdem gibt es hilfreiche Tools, die dich dabei unterstützen.
// Union Type
type Ergebnis = string | number | null;
type Status = "aktiv" | "inaktiv" | "geloescht";
// Literal Types – exakte Werte
type HttpMethode = "GET" | "POST" | "PUT" | "DELETE";
type Richtung = "links" | "rechts" | "oben" | "unten";
function httpAnfrage(url: string, methode: HttpMethode): void {
// methode kann nur GET, POST, PUT oder DELETE sein
}
// Discriminated Unions – maechtig!
interface Kreis {
art: "kreis";
radius: number;
}
interface Rechteck {
art: "rechteck";
breite: number;
hoehe: number;
}
type Form = Kreis | Rechteck;
function flaeche(form: Form): number {
switch (form.art) {
case "kreis":
return Math.PI * form.radius ** 2;
case "rechteck":
return form.breite * form.hoehe;
}
}
// Type Narrowing
function verarbeite(wert: string | number): string {
if (typeof wert === "string") {
return wert.toUpperCase(); // TS weiss: wert ist string
}
return wert.toFixed(2); // TS weiss: wert ist number
}
Darüber hinaus lässt sich das Beispiel leicht erweitern.
8. Utility Types
Allerdings gibt es einige wichtige Unterschiede zu beachten.
TypeScript bietet eingebaute Utility Types die das Leben leichter machen:
interface User {
id: number;
name: string;
email: string;
passwort: string;
}
// Partial – alle Felder optional
type UserUpdate = Partial<User>;
// { id?: number; name?: string; email?: string; passwort?: string; }
// Required – alle Felder pflicht
type StrikterUser = Required<User>;
// Pick – nur bestimmte Felder
type UserPreview = Pick<User, "id" | "name">;
// { id: number; name: string; }
// Omit – Felder ausschliessen
type OeffentlicherUser = Omit<User, "passwort">;
// { id: number; name: string; email: string; }
// Record – Key-Value Map
type UserRollen = Record<string, string[]>;
const rollen: UserRollen = {
admin: ["alles"],
editor: ["posts.edit", "posts.create"],
viewer: ["posts.read"]
};
// Readonly
type UnveraenderlicherUser = Readonly<User>;
// ReturnType
function erstelleUser() {
return { id: 1, name: "Metin" };
}
type NeuerUser = ReturnType<typeof erstelleUser>;
// { id: number; name: string; }
Somit sparst du Zeit und erhältst qualitativ hochwertigeren Output.
9. TypeScript mit React
Dabei spielen mehrere Faktoren eine wichtige Rolle.
// Component Props typisieren
interface ButtonProps {
label: string;
onClick: () => void;
variante?: "primary" | "secondary" | "danger";
disabled?: boolean;
kinder?: React.ReactNode;
}
const Button: React.FC<ButtonProps> = ({
label,
onClick,
variante = "primary",
disabled = false
}) => {
return (
<button
className={`btn btn-${variante}`}
onClick={onClick}
disabled={disabled}
>
{label}
</button>
);
};
// useState mit Typen
const [user, setUser] = useState<User | null>(null);
const [items, setItems] = useState<string[]>([]);
const [count, setCount] = useState<number>(0);
// Event Handler
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setName(e.target.value);
};
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
// ...
};
// Custom Hook mit Typen
function useFetch<T>(url: string): {
data: T | null;
loading: boolean;
error: Error | null;
} {
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<Error | null>(null);
useEffect(() => {
fetch(url)
.then(res => res.json())
.then(setData)
.catch(setError)
.finally(() => setLoading(false));
}, [url]);
return { data, loading, error };
}
Dabei zeigt dieses Beispiel den grundlegenden Ansatz.
10. Best Practices
Im Folgenden findest du alle wichtigen Details dazu.
- Strict Mode aktivieren:
"strict": truein tsconfig.json - Kein
any: Nutzeunknownstattdessen - Interface fuer Objekte: Zusätzlich type Alias fuer Unions und Primitives
- Generics nutzen: Ferner fuer wiederverwendbare Funktionen und Klassen
- Utility Types: Ebenfalls partial, Pick, Omit statt neue Interfaces
- Type Narrowing: typeof, instanceof, Discriminated Unions
- AI nutzen: GitHub Copilot generiert TypeScript-Typen automatisch
Naechste Schritte
Dennoch solltest du einige Besonderheiten beachten.
- Praxiskurs: Nimm einen TypeScript-Kurs auf Udemy
- React + TypeScript: Ebenso lerne React mit TypeScript im React-Kurs
- AI fuer TypeScript: Lies unseren Guide zu AI fuer TypeScript-Entwicklung
- REST APIs: Bau typsichere APIs mit unserem REST API Tutorial
Tipp: GitHub Copilot ist besonders stark mit TypeScript – es versteht deine Typen und generiert passenden Code. Zusammen mit VS Code hast du die beste TypeScript-Entwicklungsumgebung.