TypeScript Generics in Vue 3: Flexibler Code ohne Typverlust
TL;DR: TypeScript Generics sind der elegante Mittelweg zwischen any-Chaos und copy-paste-Duplikaten. Jakub Andrzejewski vom Nuxt Ecosystem Team zeigt in einem aktuellen Praxis-Guide, wie Generic-Typen, ApiResponse<T>-Wrapper und keyof-Constraints Vue-Projekte typsicher und skalierbar machen.
Wer mit TypeScript in Vue-Projekten arbeitet, kennt das Dilemma: entweder man schreibt denselben Typ fünfmal mit leicht veränderten Datentypen, oder man greift zur any-Keule und verliert dabei Autocomplete, Typ-Inferenz und die Sicherheit, dass der Code zur Laufzeit tut, was man erwartet. TypeScript Generics lösen genau dieses Problem — und sie fügen sich besonders elegant in die Composition API von Vue 3 ein.
Die wichtigsten Punkte
- 📅 Veröffentlicht: 30. März 2026 auf DEV Community
- 🎯 Zielgruppe: Vue 3 Entwickler:innen mit TypeScript-Grundkenntnissen
- 💡 Kernfeature: Generische Typen als wiederverwendbare Typ-Platzhalter ohne Verlust von Type Safety
- 🔧 Tech-Stack: TypeScript, Vue 3 Composition API, Nuxt, VueUse
Was bedeutet das für Vue-Entwickler:innen?
Die Composition API von Vue 3 war der entscheidende Schritt hin zu erstklassiger TypeScript-Integration. Generics bringen diesen Ansatz auf die nächste Stufe: Statt für jede API-Route einen eigenen Response-Typen zu definieren, schreibt man einmal ApiResponse<T> — und das gesamte Projekt profitiert davon.
Besonders in Nuxt-Projekten mit vielen useFetch-Calls zahlt sich das aus. Anstatt bei jedem Datenabruf den Typ manuell zu casten, lässt sich ein typsicherer Composable definieren, der den Response-Typ als Generic-Parameter entgegennimmt.
Das Grundprinzip: Typ-Platzhalter statt any
Das Problem beginnt harmlos. Eine Funktion soll für verschiedene Typen funktionieren. Die schnelle Lösung:
function identity(value: any): any {
return value
}
Das funktioniert — aber man verliert Typ-Inferenz, Autocomplete und mögliche Compiler-Fehler, die echte Bugs verhindern könnten. Die Alternative ohne Generics führt zu Code-Duplikaten, die den DRY-Prinzipien widersprechen:
function identityString(value: string): string { return value }
function identityNumber(value: number): number { return value }
Mit Generics wird daraus eine einzige, typsichere Funktion:
function identity<T>(value: T): T {
return value
}
T ist ein Typ-Platzhalter, der beim Aufruf automatisch durch den konkreten Typ ersetzt wird. TypeScript inferiert den Rückgabetyp direkt aus dem Argument.
Praktische Anwendungen in Vue & Nuxt
Pattern 1: Wiederverwendbarer ApiResponse-Typ
Das häufigste und wertvollste Einsatzgebiet in Vue-Projekten ist ein generischer Wrapper für API-Antworten:
type ApiResponse<T> = {
data: T
error: string | null
}
In einem Nuxt-Projekt definiert man diesen Typ einmal in types/api.ts und nutzt ihn project-weit:
type User = { id: number; name: string }
const response: ApiResponse<User> = {
data: { id: 1, name: "Jakub" },
error: null
}
Kombiniert mit useFetch in Nuxt ergibt sich ein typsicheres Datenabruf-Muster:
const { data, error } = await useFetch<ApiResponse<User[]>>('/api/users')
// data.value?.data ist automatisch User[] — kein Type-Cast nötig
Pattern 2: keyof-Constraints für typsichere Zugriffe
Gerade in Form-Composables oder dynamischen Tabellenkomponenten ist folgender Pattern Gold wert:
function getProperty<T, K extends keyof T>(obj: T, key: K) {
return obj[key]
}
const user = { id: 1, name: "Jakub" }
getProperty(user, "name") // ✅ TypeScript kennt den Rückgabetyp: string
getProperty(user, "age") // ❌ Compiler-Fehler — "age" existiert nicht auf User
Für Vue-Entwickler:innen besonders relevant: Dieser Ansatz lässt sich direkt in Composables für reaktive Formularfelder übersetzen.
Pattern 3: Generic Props in Vue-Komponenten
Vue 3.3+ (seit Mai 2023) erlaubt generische Komponenten direkt über das generic Attribut auf <script setup>. Das ermöglicht vollständig typisierte Listenkomponenten ohne Code-Duplikation:
<!-- Generische Listenkomponente -->
<script setup lang="ts" generic="T">
defineProps<{
items: T[]
}>()
</script>
Wichtig: Das generic="T" Attribut auf dem <script setup lang="ts"> Tag ist zwingend erforderlich — erst dadurch wird T als Typ-Parameter verfügbar. Die Komponente wird dann typsicher auf den Datentyp spezialisiert, sobald man sie mit konkreten Daten verwendet — die IDE kennt dann alle Properties der List-Items.
Developer Experience verbessert sich durch…
Die Verbesserungen sind spürbar im Alltag:
Autocomplete überall: Statt any-Typen, die die IDE zum Schweigen bringen, erhält man bei jedem Zugriff auf Generic-Daten vollständige Typ-Vorschläge.
Refactoring-Sicherheit: Ändert sich die Struktur eines API-Response-Typs, zeigt TypeScript sofort alle Stellen im Code, die angepasst werden müssen — quer durch alle Composables und Komponenten, die ApiResponse<T> nutzen.
Kein Cast-Overhead: Mit gut definierten Generics entfällt das manuelle as User[] an jeder Stelle. Der Typ fließt automatisch durch den Code.
Elegante Composables: Ein typsicheres useFetch<T> oder useLocalStorage<T> aus VueUse ist das direkte Ergebnis dieser Technik.
Praktische Nächste Schritte
- Startet mit
ApiResponse<T>: Legt in eurem nächsten Nuxt- oder Vue-Projekt einetypes/api.tsan und definiert dort einen generischen Response-Wrapper. Das zahlt sich sofort aus. - Refactored bestehende Composables: Schaut euch eure Custom Composables an — überall wo
anysteht oder mehrere fast-identische Funktionen existieren, sind Generics die richtige Antwort. - Jakubs weiterführenden Artikel lesen: Er hat einen separaten Deep-Dive zu generischen Props in Vue-Komponenten veröffentlicht, der die
<script setup generic>Syntax ausführlich behandelt. keyof-Pattern für Formulare anwenden: Wer dynamische Formular-Composables baut, sollteK extends keyof Tals Standard-Werkzeug in sein Repertoire aufnehmen.
Robin Böhm
Gründer von vuejs.de
Entwickler, Trainer und Buch-Autor
Robin beschäftigt sich seit 2012 intensiv mit der Erstellung client-seitiger Web-Applikationen. Mit seinem Schulungs-Unternehmen workshops.de bildet er Teams mit dem Fokus auf Web-Technologien aus.
Weitere Artikel
CSP Nonce in Nuxt: Inline Scripts sicher erlauben
CSP Nonce in Nuxt: Inline Scripts sicher erlauben
TypeScript 6.0: Was Vue-Projekte jetzt wissen müssen
TypeScript 6.0: Was Vue-Projekte jetzt wissen müssen
Vue State Management: Composables, Provide/Inject und Pinia – Die richtige Wahl für jede Situation
Vue State Management: Composables, Provide/Inject und Pinia – Die richtige Wahl für jede Situation