Discriminated Unions für Component-Varianten
Modellieren Sie Variant-Props mit Discriminated Unions, damit TypeScript gültige Prop-Kombinationen erzwingt.
Discriminated Unions für Component-Varianten ist eine kostenlose React Academy-Lektion auf CoddyKit. Dies ist Lektion 1 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des React Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der React Academy-Kurs umfasst insgesamt 4 Lektionen.
Das Problem mit Variant-Props
Eine Komponente mit optionalen Props für verschiedene Modi (z. B. ein Button, der entweder ein Link oder ein Button ist) kann ungültige Prop-Kombinationen zulassen. TypeScript kann sie ohne Discriminated Unions nicht erkennen.
Was ist eine Discriminated Union?
Eine Discriminated Union ist eine Union von Typen, die ein gemeinsames Feld mit einem Literaltyp (den Discriminant) haben. TypeScript grenzt den Typ anhand des Werts dieses Feldes ein.
type Shape =
| { kind: 'circle'; radius: number }
| { kind: 'rectangle'; width: number; height: number };
function area(shape: Shape): number {
if (shape.kind === 'circle') return Math.PI * shape.radius ** 2;
return shape.width * shape.height; // TS knows width/height exist here
}Button- und Link-Varianten
Modellieren Sie eine polymorphe Komponente mit einer Discriminated Union auf einem as- oder variant-Feld, um für jeden Fall die korrekten Props zu erzwingen.
type ButtonProps =
| { as: 'button'; onClick: () => void; disabled?: boolean; children: React.ReactNode }
| { as: 'a'; href: string; target?: string; children: React.ReactNode };
function ActionButton(props: ButtonProps) {
if (props.as === 'button') {
return <button onClick={props.onClick} disabled={props.disabled}>{props.children}</button>;
}
return <a href={props.href} target={props.target}>{props.children}</a>;
}Varianten der Alert-Komponente
Modellieren Sie einen Alert mit unterschiedlichen erforderlichen Daten für jeden Severity-Typ.
type AlertProps =
| { type: 'success'; message: string }
| { type: 'error'; message: string; onRetry: () => void }
| { type: 'warning'; message: string; details?: string };
function Alert(props: AlertProps) {
if (props.type === 'error') {
return (
<div className="alert error">
<p>{props.message}</p>
<button onClick={props.onRetry}>Retry</button>
</div>
);
}
return <div className={`alert ${props.type}`}>{props.message}</div>;
}Typ-Eingrenzung in Event-Handlern
Discriminated Unions funktionieren auch mit ereignisgesteuerten Daten – ideal für State Machines oder aktionsbasierten State.
type LoadingState<T> =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success'; data: T }
| { status: 'error'; error: Error };
function DataView<T>({ state }: { state: LoadingState<T> }) {
if (state.status === 'loading') return <Spinner />;
if (state.status === 'error') return <p>{state.error.message}</p>;
if (state.status === 'success') return <pre>{JSON.stringify(state.data)}</pre>;
return null;
}Vollständigkeitsprüfungen mit never
Fügen Sie im default-Zweig eine never-Prüfung hinzu, damit TypeScript einen Fehler meldet, wenn ein neues Union-Mitglied hinzugefügt, aber nicht behandelt wurde.
function assertNever(x: never): never {
throw new Error('Unhandled case: ' + x);
}
function renderIcon(type: AlertProps['type']) {
switch (type) {
case 'success': return <CheckIcon />;
case 'error': return <XIcon />;
case 'warning': return <WarnIcon />;
default: return assertNever(type); // TS error if a case is missing
}
}Discriminated Unions für API-Antworten
Modellieren Sie die Formen von API-Antworten als Discriminated Unions, damit Aufrufer Erfolgs- und Fehlerpfade ohne Type Casting behandeln.
type ApiResult<T> =
| { ok: true; data: T }
| { ok: false; error: string; code: number };
async function fetchUser(id: string): Promise<ApiResult<User>> {
const res = await fetch(`/api/users/${id}`);
if (!res.ok) return { ok: false, error: 'Not found', code: res.status };
return { ok: true, data: await res.json() };
}Type Guards zur Typ-Eingrenzung
Verwenden Sie benutzerdefinierte Type Guards, um Unions in komplexeren Szenarien einzugrenzen, in denen der Discriminant nicht einfach per Gleichheitsprüfung ermittelt wird.
function isSuccess<T>(result: ApiResult<T>): result is { ok: true; data: T } {
return result.ok === true;
}
const result = await fetchUser('1');
if (isSuccess(result)) {
console.log(result.data.name); // TS knows data exists
}Optional-Prop-Suppe vermeiden
Ohne Discriminated Unions sammeln sich in Komponenten optionale Props an, die nur in bestimmten Kombinationen gültig sind – verwirrend und nicht typsicher. Discriminated Unions beseitigen unmögliche Zustände.
// Bad: optional prop soup — invalid combos allowed:
interface BadProps {
href?: string;
onClick?: () => void;
disabled?: boolean;
}
// Good: only valid combos via discriminated union:
type GoodProps =
| { as: 'a'; href: string }
| { as: 'button'; onClick: () => void; disabled?: boolean };Unions zusammensetzen
Verwenden Sie & (Intersection), um allen Mitgliedern einer Union gemeinsame Props hinzuzufügen.
type BaseProps = { className?: string; children: React.ReactNode };
type ButtonVariant =
| (BaseProps & { variant: 'primary'; onClick: () => void })
| (BaseProps & { variant: 'link'; href: string });Discrimination zur Laufzeit
React verwendet den Discriminant zur Laufzeit, um die richtige UI zu rendern. TypeScript verwendet ihn zur Compile-Zeit, um die korrekte Verwendung von Props zu erzwingen. Beide Ebenen sind geschützt.
Kurzer Test
Was ist der Discriminant in einer Discriminated Union?
Zusammenfassung
Discriminated Unions modellieren Komponenten mit sich gegenseitig ausschließenden Prop-Mengen, indem sie ein Feld mit einem Literaltyp als gemeinsamen Discriminant verwenden. Verwenden Sie never im default-Zweig für Vollständigkeitsprüfungen. Sie beseitigen ungültige Prop-Kombinationen, die optionale Props zulassen, und machen Komponenten selbstdokumentierend und typsicher.
Lerne React mit einem KI-Tutor — kostenlos
Schreibe und führe echten Code in deinem Browser aus, bekomme sofortige Hilfe von einem 24/7 KI-Tutor und setze dein Lernen im Web oder in der App fort.
- Kurse
- 88
- Lektionen
- 324
Häufig gestellte Fragen
Ist die Lektion „Discriminated Unions für Component-Varianten“ kostenlos?
Ja — der vollständige Text von „Discriminated Unions für Component-Varianten“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des React Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der React Academy-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Discriminated Unions für Component-Varianten“?
Modellieren Sie Variant-Props mit Discriminated Unions, damit TypeScript gültige Prop-Kombinationen erzwingt. Du übst React Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um React Academy zu starten?
Keine Vorkenntnisse erforderlich. React Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 1 von 4.
Wie lange dauert die Lektion „Discriminated Unions für Component-Varianten“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser React Academy-Lektion Code schreiben und ausführen?
Ja. Jede React Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Discriminated Unions für Component-Varianten
- Bedingte und gemappte Types in React
- Polymorphe Components mit der 'as'-Prop
- Typsichere Formulare und API-Response-Verträge