von der Wiki-Leiche zum gelebten Standard
Die meisten TypeScript-Style-Guides landen als lange Wiki-Seite, die einmal geschrieben und danach nie wieder gelesen wird. Ein Style Guide, der tatsächlich wirkt, definiert einen klaren Scope, setzt Regeln automatisiert mit ESLint durch und zeigt Konventionen an echten Beispielen statt in abstrakter Prosa.
Inhaltsverzeichnis
- 1. Warum die meisten Style Guides scheitern
- 2. Scope festlegen: Was ein Style Guide regeln sollte
- 3. Regeln automatisiert durchsetzen statt nur aufschreiben
- 4. Beispiele statt Prosa: Richtig und falsch nebeneinander
- 5. Namenskonventionen für Typen, Interfaces und Generics
- 6. Strukturregeln: Dateiorganisation und Exportmuster
- 7. Den Style Guide aktiv pflegen statt einmalig schreiben
- 8. Einen bestehenden Style Guide im Team einführen
- 9. Style-Guide-Ansätze im direkten Vergleich
- 10. Zusammenfassung
- 11. FAQ
1. Warum die meisten Style Guides scheitern
Ein TypeScript-Style-Guide scheitert selten an fehlendem Willen, sondern an der Form, in der er entsteht. Ein einmalig verfasstes Wiki-Dokument mit langen Prosa-Absätzen wird gelesen, wenn es entsteht, und danach nie wieder, weil es im Alltag keine Rolle mehr spielt. Neue Regeln landen in Pull-Request-Kommentaren, statt in den Style Guide einzufließen, und die Lücke zwischen Dokument und Praxis wächst mit jedem Sprint.
Ein wirksamer TypeScript-Style-Guide unterscheidet sich in drei Punkten von einer toten Wiki-Seite: Er wird automatisiert durchgesetzt, statt nur empfohlen zu werden. Er zeigt Beispiele statt Regeln in Prosa zu formulieren. Und er lebt im Repository, versioniert neben dem Code, statt in einem separaten Dokumentationssystem zu verstauben.
2. Scope festlegen: Was ein Style Guide regeln sollte
Der häufigste Fehler beim Erstellen eines TypeScript-Style-Guides ist ein zu weiter Scope. Ein Guide, der sowohl Formatierung als auch Architektur als auch Business-Konventionen abdecken will, wird unübersichtlich und niemand liest ihn vollständig. Formatierungsfragen wie Einrückung oder Anführungszeichen gehören nicht in einen Style Guide, sondern in die Prettier-Konfiguration, wo sie automatisch und ohne Diskussion angewendet werden.
Ein TypeScript-Style-Guide sollte sich auf Entscheidungen konzentrieren, die Prettier nicht automatisch treffen kann: Wann Interface statt Type Alias, wie Generics benannt werden, welche Exportmuster für Module gelten und wie mit any umgegangen wird. Das reduziert den Guide auf das, was tatsächlich Diskussion und Konvention braucht, statt Formatierungsfragen zu wiederholen, die ein Tool längst löst.
{
"//": "prettier.config.json — handles formatting so the style guide doesn't have to",
"semi": true,
"singleQuote": false,
"trailingComma": "all",
"printWidth": 100,
"tabWidth": 2
}
3. Regeln automatisiert durchsetzen statt nur aufschreiben
Eine Regel, die nur im Style Guide steht, aber nicht automatisiert geprüft wird, verschwindet nach wenigen Wochen aus dem kollektiven Gedächtnis des Teams. Jede Regel im TypeScript-Style-Guide sollte deshalb die Frage beantworten, wie sie mit ESLint oder einem Custom-Rule durchsetzbar ist. Regeln, die sich nicht automatisieren lassen, sollten kritisch hinterfragt werden, ob sie wirklich in den Guide gehören.
Die ESLint Flat Config macht es einfach, projektspezifische Regeln direkt neben den Style Guide zu legen und beide gemeinsam zu versionieren. Ein Kommentar in der Konfiguration, der auf den entsprechenden Abschnitt im Style Guide verweist, schließt die Lücke zwischen Regel und Begründung, die bei reinen ESLint-Configs sonst oft fehlt.
// eslint.config.ts — rules cross-reference the style guide sections
import tseslint from "typescript-eslint";
export default tseslint.config({
rules: {
// Style Guide §5.1: prefer interface for object shapes, type for unions
"@typescript-eslint/consistent-type-definitions": ["error", "interface"],
// Style Guide §5.3: generic type parameters use single uppercase letters
// with a descriptive suffix, e.g. TEntity, not T1 or Generic
"@typescript-eslint/naming-convention": [
"error",
{ selector: "typeParameter", format: ["PascalCase"], prefix: ["T"] },
],
// Style Guide §8.2: no default exports, always named exports
"import/no-default-export": "error",
// Style Guide §9.1: explicit any requires a linked ticket comment
"@typescript-eslint/no-explicit-any": "error",
},
});
4. Beispiele statt Prosa: Richtig und falsch nebeneinander
Entwickler lesen Codebeispiele schneller und behalten sie besser als lange Prosa-Erklärungen. Ein TypeScript-Style-Guide, der jede Regel mit einem kurzen, lauffähigen Vorher-Nachher-Beispiel zeigt, wird tatsächlich als Nachschlagewerk genutzt, während reine Textregeln meist ungelesen bleiben.
Wichtig ist, dass die Beispiele aus echten Situationen im Projekt stammen, nicht aus akademischen Spielereien. Ein Beispiel, das ein reales Review-Problem aus der eigenen Codebasis zeigt, überzeugt das Team eher als ein generisches Lehrbuch-Beispiel, das mit dem eigenen Code nichts zu tun hat.
// Style Guide §6.2: readonly arrays for data that must not be mutated
// WRONG — array can be mutated anywhere it is passed
function renderTags(tags: string[]): string {
return tags.join(", ");
}
// RIGHT — readonly signals intent and prevents accidental push/splice
function renderTagsSafely(tags: readonly string[]): string {
return tags.join(", ");
}
// Style Guide §6.4: prefer discriminated unions over optional flags
// WRONG — invalid states like { loading: true, error: "x" } are representable
interface FetchStateWrong {
loading?: boolean;
error?: string;
data?: unknown;
}
// RIGHT — only valid combinations can be constructed
type FetchState =
| { status: "loading" }
| { status: "error"; error: string }
| { status: "success"; data: unknown };
5. Namenskonventionen für Typen, Interfaces und Generics
Uneinheitliche Namenskonventionen sind eine der häufigsten Quellen für Diskussionen in Reviews, obwohl sie sich mit einem klaren Style Guide vollständig vermeiden lassen. Fragen wie ob ein Interface ein I-Präfix trägt, ob Generics IEntity oder TEntity heißen und ob Enum-Werte in UPPER_CASE oder PascalCase geschrieben werden, sollten einmal entschieden und dann per ESLint durchgesetzt werden.
Eine bewährte Konvention ist, Generics mit einem beschreibenden T-Präfix zu versehen, etwa TEntity statt nur T, sobald mehr als ein Typparameter im Spiel ist. Das macht Signaturen komplexer Funktionen lesbarer, ohne dass jeder einzelne Aufrufer die Implementierung studieren muss, um die Bedeutung der Typparameter zu verstehen.
// Style Guide §5: naming conventions in one place
// Interfaces: no I-prefix, PascalCase noun
interface OrderSummary { id: string; total: number }
// Generics with more than one parameter: descriptive T-prefix, not T1/T2
function mapEntries<TKey extends string, TValue>(
entries: readonly [TKey, TValue][],
): Record<TKey, TValue> {
return Object.fromEntries(entries) as Record<TKey, TValue>;
}
// Enum values: PascalCase, not UPPER_CASE, matches our TypeScript-first style
enum OrderStatus {
Draft = "draft",
Placed = "placed",
Shipped = "shipped",
}
// Type aliases for unions: suffix with the concept, not with "Type"
type PaymentMethod = "card" | "paypal" | "invoice"; // not PaymentMethodType
// Boolean-returning functions: is/has/can prefix, no bare adjectives
function isRefundable(order: OrderSummary): boolean {
return order.total > 0;
}
6. Strukturregeln: Dateiorganisation und Exportmuster
Neben Namen und Typmustern sollte ein TypeScript-Style-Guide auch festlegen, wo Typen im Projekt leben. Eine bewährte Konvention ist, Typen so nah wie möglich am Code zu halten, der sie verwendet, statt eine zentrale types.ts-Datei zu pflegen, die mit wachsendem Projekt unübersichtlich wird. Nur wirklich geteilte Domänentypen wandern in ein eigenes shared-Verzeichnis.
Exportmuster verdienen ebenfalls eine klare Regel: Named Exports statt Default Exports erleichtern das Refactoring, weil IDEs Umbenennungen zuverlässiger über Named Exports verfolgen können. Diese Regel lässt sich, wie viele Strukturregeln im Style Guide, direkt mit einer ESLint-Regel erzwingen, statt auf Disziplin im Review zu hoffen.
// Style Guide §8: co-locate types, only shared domain types move out
// src/features/orders/order.types.ts — lives next to its feature
export interface Order { id: string; total: number }
// src/shared/types/money.ts — genuinely shared across features, moved out
export interface Money { amount: number; currency: string }
// WRONG per Style Guide §8.2 — default export makes renames harder to track
export default function formatOrder(order: Order): string {
return `#${order.id}: ${order.total}`;
}
// RIGHT — named export, IDE refactors track this reliably
export function formatOrderSafely(order: Order): string {
return `#${order.id}: ${order.total}`;
}
7. Den Style Guide aktiv pflegen statt einmalig schreiben
Ein TypeScript-Style-Guide ist nie fertig. Neue Sprachfeatures, neue Bibliotheken und neue Erfahrungen aus Produktionsfehlern verändern, welche Konventionen sinnvoll sind. Ein Style Guide, der im Repository neben dem Code liegt und über normale Pull Requests aktualisiert wird, bleibt lebendig, weil Änderungen denselben Review-Prozess durchlaufen wie Code-Änderungen.
Ein einfacher Mechanismus, um Pflege zu erzwingen, ist eine Pflicht, jede neue ESLint-Regel gleichzeitig mit einem Abschnitt im Style Guide zu ergänzen. So wachsen Regel-Set und Dokumentation immer synchron, statt dass eines dem anderen hinterherhinkt.
8. Einen bestehenden Style Guide im Team einführen
Ein neuer TypeScript-Style-Guide sollte nie über Nacht mit voller ESLint-Strenge über eine bestehende Codebasis rollen. Ein sanfterer Weg ist, neue Regeln zunächst als warn statt error zu konfigurieren und erst nach einer Übergangsphase auf error zu heben, sobald bestehende Verstöße bereinigt sind.
Ebenso wichtig ist eine kurze, gemeinsame Vorstellung des Style Guides im Team-Meeting, statt ihn einfach per Link zu verschicken. Ein Team, das versteht, warum eine Regel existiert, akzeptiert sie eher, als wenn ESLint plötzlich unerklärte Fehler in bestehenden Pull Requests wirft.
9. Style-Guide-Ansätze im direkten Vergleich
Die Form eines TypeScript-Style-Guides entscheidet stärker über seinen Erfolg als sein Inhalt. Die folgende Übersicht zeigt, welche Praktiken einen Style Guide zur toten Wiki-Seite machen und welche ihn tatsächlich am Leben halten.
| Aspekt | Toter Style Guide | Gelebter Style Guide | Effekt |
|---|---|---|---|
| Speicherort | Separates Wiki-System | Im Repository, neben dem Code | Wird mit Pull Requests aktualisiert |
| Format | Lange Prosa-Absätze | Kurze Vorher-Nachher-Codebeispiele | Schneller lesbar und behaltbar |
| Durchsetzung | Nur Empfehlung im Review | ESLint-Regel pro Style-Guide-Abschnitt | Verstöße fallen automatisch auf |
| Scope | Formatierung und Architektur gemischt | Nur Entscheidungen, die Prettier nicht trifft | Übersichtlich und fokussiert |
| Einführung | Sofort mit voller Strenge | Schrittweise von warn zu error | Akzeptanz statt Frustration |
10. Zusammenfassung
Ein TypeScript-Style-Guide wirkt nur, wenn er die drei zentralen Fallen vermeidet, die die meisten Guides zu toten Wiki-Seiten machen: fehlende Automatisierung, zu viel Prosa und ein zu weiter Scope. Wer Regeln direkt mit ESLint verknüpft, Beispiele statt Prosa nutzt und den Guide auf das beschränkt, was Prettier nicht ohnehin regelt, erhält ein Dokument, das im Alltag tatsächlich nachgeschlagen wird.
Genauso entscheidend ist die aktive Pflege im Repository und eine schrittweise Einführung bei bestehenden Codebasen. Ein Style Guide, der mit dem Code versioniert wird und neue Regeln nur zusammen mit einer Begründung aufnimmt, bleibt über Jahre hinweg relevant, statt nach wenigen Monaten zu veralten.
TypeScript-Style-Guide erstellen, das Wichtigste auf einen Blick
Scope begrenzen
Nur Entscheidungen regeln, die Prettier nicht automatisch trifft, sonst wird der Guide unübersichtlich.
Automatisiert durchsetzen
Jede Regel braucht eine ESLint-Entsprechung, sonst verschwindet sie nach wenigen Wochen aus dem Alltag.
Beispiele statt Prosa
Kurze Vorher-Nachher-Codebeispiele aus echten Projektsituationen statt langer Textabschnitte.
Im Repository pflegen
Der Guide lebt neben dem Code und wächst synchron mit jeder neuen ESLint-Regel.