So organisieren Sie Typdefinitionen in einem TypeScript-Projekt
Die meisten TypeScript-Projekte beginnen auf die gleiche Weise: eine einzelne types.ts-Datei, die langsam auf Hunderte von Zeilen anwächst. Irgendetwas zu finden wird zur lästigen Pflicht. Die Wiederverwendung von Typen über mehrere Dateien hinweg fühlt sich riskant an. Neue Teammitglieder wissen nicht, wo sie suchen sollen.
Die gute Nachricht ist, dass die Organisation von TypeScript-Typen kein komplexes System erfordert. Sie erfordert eine klare Regel: Platzieren Sie Typen so nah wie möglich an der Stelle, wo sie verwendet werden, und verschieben Sie sie nur dann, wenn sie an anderer Stelle benötigt werden.
So wenden Sie diese Regel in jeder Phase eines Projekts an.
Wichtigste Erkenntnisse
- Platzieren Sie Typen so nah wie möglich an ihrer Verwendung und befördern Sie sie nur dann an gemeinsame Speicherorte, wenn mehrere Dateien sie benötigen.
- Verwenden Sie
.ts-Dateien für explizite Typ-Exporte und -Importe; reservieren Sie.d.ts-Dateien ausschließlich für Ambient-Deklarationen wie Umgebungsvariablen oder globale Erweiterungen. - Führen Sie eine konsistente Namenskonvention ein, wie z. B.
*.types.tsfür modulspezifische Typen und Barrel-index.ts-Dateien für saubere, stabile Importpfade. - Stellen Sie in Monorepos oder gemeinsam genutzten Paketen Typen über die
types-Bedingung in denpackage.json-Exports bereit und halten Sie interne Typen privat.
Die zentrale Entscheidung: Wo sollte ein Typ leben?
Stellen Sie sich eine Frage: Wie viele Dateien benötigen diesen Typ?
- Eine Datei → definieren Sie ihn inline in dieser Datei
- Ein paar Dateien im selben Modul → platzieren Sie ihn in einer gemeinsamen
.types.ts-Datei in der Nähe - Im gesamten Projekt → verschieben Sie ihn in ein gemeinsames
src/types/-Verzeichnis - Über Pakete hinweg → veröffentlichen Sie ihn aus einem dedizierten Typen-Paket
Diese Progression hält die Typdefinitionen Ihres Projekts organisiert, ohne von Anfang an zu überentwickeln.
Muster 1: Inline-Typen für lokale Verwendung
Wenn ein Typ nur in einer Datei verwendet wird, definieren Sie ihn dort. Keine separate Datei erforderlich.
// UserCard.tsx
interface UserCardProps {
name: string
avatarUrl: string
role: "admin" | "viewer"
}
export function UserCard({ name, avatarUrl, role }: UserCardProps) {
// ...
}
Dies ist die richtige Standardeinstellung. Vorzeitige Abstraktion erzeugt Indirektion ohne Nutzen.
Muster 2: Colocated Type Files für gemeinsame Modultypen
Wenn zwei oder mehr Komponenten im selben Ordner Typen teilen, extrahieren Sie diese in eine colocated .types.ts-Datei.
src/components/user/
├── UserCard.tsx
├── UserList.tsx
└── user.types.ts ← gemeinsame Typen für dieses Modul
Dies hält verwandte Typen nah am Code, der sie verwendet, ohne eine globale Datei zu überladen.
Muster 3: Ein gemeinsames types/-Verzeichnis für übergreifende Definitionen
Wenn Typen über mehrere nicht verwandte Module hinweg verwendet werden, ist ein zentrales src/types/-Verzeichnis sinnvoll. Verwenden Sie eine Barrel-index.ts, um Importe sauber und stabil zu halten.
src/types/
├── index.ts ← exportiert alles erneut
├── api.types.ts
├── user.types.ts
└── product.types.ts
// src/types/index.ts
export type { ApiResponse, PaginatedResult } from "./api.types"
export type { User, UserRole } from "./user.types"
Verbraucher importieren von einem Pfad: import type { User } from "@/types". Wenn Sie später die Interna reorganisieren, ändern sich die Importpfade nicht.
Discover how at OpenReplay.com.
Sollten Sie .ts oder .d.ts für Typdefinitionen verwenden?
Dies ist einer der häufigsten Verwirrungspunkte bei der Organisation von TypeScript-Typen.
Verwenden Sie .ts-Dateien für Typen, die Sie explizit exportieren und importieren. Dies ist die richtige Wahl für fast alles in einer Anwendung.
Verwenden Sie .d.ts-Dateien hauptsächlich für Ambient-Deklarationen – Situationen, in denen Sie TypeScript über etwas informieren müssen, das zur Laufzeit existiert, aber keine TypeScript-Quelle hat. Häufige Beispiele:
env.d.ts– Deklaration vonimport.meta.env-Variablen für Vite oder ähnliche Bundlerglobal.d.ts– Erweiterung von Drittanbieter-Modultypen oder Deklaration globaler Variablen
// env.d.ts
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_API_URL: string
}
Einige moderne Projekte konfigurieren compilerOptions.types explizit, um zu steuern, welche Ambient-Typen geladen werden, während andere sich auf die automatische @types-Erkennung verlassen. Wenn Sie eine Bundler-basierte Toolchain wie Vite oder Next.js verwenden, folgen Sie deren empfohlenen Konventionen für diese Dateien, anstatt freistehende globale Deklarationen zu erstellen.
Namenskonventionen, die skalieren
Konsistente Benennung reduziert die kognitive Last im Team:
| Muster | Beispiel | Anwendungsfall |
|---|---|---|
*.types.ts | user.types.ts | Modulspezifische Typen |
index.ts | types/index.ts | Barrel-Re-Export |
env.d.ts | env.d.ts | Umgebungsvariablen-Deklarationen |
global.d.ts | global.d.ts | Drittanbieter-Typ-Erweiterung |
Vermeiden Sie IUser-Präfixe und UserType-Suffixe. Einfache Namen wie User und ApiResponse sind sauberer und entsprechen modernen TypeScript-Konventionen.
Organisation von TypeScript-Typen in einem gemeinsam genutzten Paket
Wenn Sie eine Bibliothek erstellen oder in einem Monorepo arbeiten, stellen Sie Typen über package.json-Exports unter Verwendung der types-Bedingung bereit, anstatt sich auf ältere typesVersions-Muster zu verlassen.
{
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
}
}
}
Halten Sie interne Typen privat – exportieren Sie sie nicht vom Paket-Einstiegspunkt. Nur die öffentliche API-Oberfläche sollte für Verbraucher sichtbar sein.
Fazit
Beginnen Sie mit Inline-Typen. Extrahieren Sie sie in eine colocated Datei, wenn eine zweite Datei sie benötigt. Befördern Sie sie zu src/types/, wenn sie wirklich übergreifend sind. Verwenden Sie .d.ts-Dateien nur für Ambient-Deklarationen, nicht als Standard-Speicherort für alle Typdefinitionen.
Das Ziel der Organisation von TypeScript-Typen ist keine perfekte Ordnerstruktur – es geht darum, dem nächsten Entwickler (oder Ihrem zukünftigen Ich) zu ermöglichen, Typen ohne Reibung zu finden und wiederzuverwenden.
Häufig gestellte Fragen
Nein. Eine einzelne Datei funktioniert anfangs, wird aber mit dem Wachstum eines Projekts schwer zu navigieren. Halten Sie stattdessen Typen nah an der Stelle, wo sie verwendet werden. Definieren Sie sie inline für die Verwendung in einer einzelnen Datei, extrahieren Sie sie in eine colocated .types.ts-Datei, wenn sie innerhalb eines Moduls geteilt werden, und befördern Sie sie nur dann in ein zentrales types-Verzeichnis, wenn sie über nicht verwandte Teile der Codebasis hinweg benötigt werden.
Verwenden Sie .ts-Dateien für Typen, die Sie in Ihrem Anwendungscode explizit exportieren und importieren. Verwenden Sie .d.ts-Dateien nur für Ambient-Deklarationen, wie z. B. die Beschreibung von Umgebungsvariablen oder die Erweiterung von Drittanbieter-Modultypen. Das Platzieren regulärer Anwendungstypen in .d.ts-Dateien kann Verwirrung stiften, da diese Deklarationen global verfügbar sind, ohne dass ein expliziter Import erforderlich ist.
Eine weit verbreitete Konvention ist die Verwendung des Musters modul-name.types.ts für modulspezifische Typen und einer index.ts-Barrel-Datei für Re-Exports in einem gemeinsamen types-Verzeichnis. Vermeiden Sie ungarische Notation wie IUser oder redundante Suffixe wie UserType. Einfache, beschreibende Namen wie User und ApiResponse werden in modernen TypeScript-Projekten bevorzugt.
Verwenden Sie die types-Bedingung innerhalb des exports-Feldes Ihrer package.json, um auf Ihre kompilierte Deklarationsdatei zu verweisen. Dieser Ansatz ist expliziter und zuverlässiger als das ältere typesVersions-Muster. Exportieren Sie nur Typen, die Teil Ihrer öffentlichen API sind, und halten Sie interne Typen privat, um zu vermeiden, dass Implementierungsdetails an Verbraucher weitergegeben werden.
Complete picture for complete understanding
Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.
Check our GitHub repo and join the thousands of developers in our community.