Praxis

TypeScript mit React: Komponenten richtig typisieren

Props, State, Events und Refs in React-Komponenten mit TypeScript typisieren. Praxisbeispiele für funktionale Komponenten und Hooks.

Lesezeit 7 Min. Aktualisiert 26.05.2026 1 Quellen Jan-Tristan Rudat Jan-Tristan Rudat
Inhalt

TypeScript mit React: Komponenten richtig typisieren

React und TypeScript ergänzen sich hervorragend. TypeScript gibt dir Typsicherheit für Props, State, Event-Handler und Refs, und macht es deutlich einfacher, Fehler frühzeitig zu finden. Dieser Ratgeber zeigt die wichtigsten Muster für die tägliche Arbeit.

Props typisieren

Der häufigste Anwendungsfall ist das Definieren eines Interfaces für die Props einer Komponente.

interface KnopfProps {
  beschriftung: string;
  onClick: () => void;
  deaktiviert?: boolean;
  variante?: "primaer" | "sekundaer" | "gefahr";
}

function Knopf({ beschriftung, onClick, deaktiviert = false, variante = "primaer" }: KnopfProps) {
  return (
    <button
      onClick={onClick}
      disabled={deaktiviert}
      className={`btn btn-${variante}`}
    >
      {beschriftung}
    </button>
  );
}

TypeScript prüft beim Aufruf, ob alle Pflicht-Props angegeben sind und ob die Typen stimmen.

Children typisieren

Wenn deine Komponente Kinder-Elemente akzeptiert, verwendest du React.ReactNode als Typ.

interface KarteProps {
  titel: string;
  children: React.ReactNode;
}

function Karte({ titel, children }: KarteProps) {
  return (
    <div className="karte">
      <h2>{titel}</h2>
      <div className="karte-inhalt">{children}</div>
    </div>
  );
}

useState mit Typen

React leitet den Typ von useState aus dem Initialwert ab. Bei komplexeren Strukturen oder wenn der Initialwert null ist, gibst du den Typen explizit an.

interface Formularwerte {
  name: string;
  email: string;
  nachricht: string;
}

function KontaktFormular() {
  const [werte, setWerte] = React.useState<Formularwerte>({
    name: "",
    email: "",
    nachricht: "",
  });

  const [fehler, setFehler] = React.useState<string | null>(null);
  const [gesendet, setGesendet] = React.useState(false);

  // TypeScript weiß: werte ist Formularwerte, fehler ist string | null, gesendet ist boolean
  return <div>{/* ... */}</div>;
}

Event-Handler typisieren

Event-Handler in React haben spezifische Typen, die vom Element und der Art des Events abhängen.

function Suche() {
  const [suchbegriff, setSuchbegriff] = React.useState("");

  const handleAenderung = (event: React.ChangeEvent<HTMLInputElement>) => {
    setSuchbegriff(event.target.value);
  };

  const handleAbsenden = (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    console.log("Suche nach:", suchbegriff);
  };

  return (
    <form onSubmit={handleAbsenden}>
      <input
        type="text"
        value={suchbegriff}
        onChange={handleAenderung}
        placeholder="Suchbegriff eingeben"
      />
      <button type="submit">Suchen</button>
    </form>
  );
}

useRef typisieren

useRef wird für DOM-Referenzen und für veränderbare Werte verwendet, die kein Re-Render auslösen sollen.

function FokusEingabe() {
  // DOM-Referenz: Typ des Elements angeben, null als Initialwert
  const eingabeRef = React.useRef<HTMLInputElement>(null);

  const fokussieren = () => {
    // Optional Chaining nötig, da ref.current null sein kann
    eingabeRef.current?.focus();
  };

  return (
    <div>
      <input ref={eingabeRef} type="text" />
      <button onClick={fokussieren}>Fokussieren</button>
    </div>
  );
}

useReducer mit Typen

Bei komplexem State ist useReducer oft sauberer als mehrere useState-Aufrufe. TypeScript hilft dabei, alle Action-Typen vollständig zu behandeln.

type AufgabeAktion =
  | { type: "HINZUFUEGEN"; titel: string }
  | { type: "ABSCHLIESSEN"; id: number }
  | { type: "LOESCHEN"; id: number };

interface Aufgabe {
  id: number;
  titel: string;
  erledigt: boolean;
}

interface AufgabenZustand {
  aufgaben: Aufgabe[];
  naechsteId: number;
}

function aufgabenReducer(zustand: AufgabenZustand, aktion: AufgabeAktion): AufgabenZustand {
  switch (aktion.type) {
    case "HINZUFUEGEN":
      return {
        aufgaben: [
          ...zustand.aufgaben,
          { id: zustand.naechsteId, titel: aktion.titel, erledigt: false },
        ],
        naechsteId: zustand.naechsteId + 1,
      };
    case "ABSCHLIESSEN":
      return {
        ...zustand,
        aufgaben: zustand.aufgaben.map((a) =>
          a.id === aktion.id ? { ...a, erledigt: true } : a
        ),
      };
    case "LOESCHEN":
      return {
        ...zustand,
        aufgaben: zustand.aufgaben.filter((a) => a.id !== aktion.id),
      };
  }
}

Der Compiler prüft, ob alle Fälle behandelt wurden. Vergisst du einen case, gibt es einen Fehler.

Generische Komponenten

Manchmal willst du eine Komponente, die mit verschiedenen Datentypen funktioniert. Dann verwendest du generische Komponenten.

interface ListenProps<T> {
  elemente: T[];
  renderElement: (element: T, index: number) => React.ReactNode;
  leerText?: string;
}

function Liste<T>({ elemente, renderElement, leerText = "Keine Einträge" }: ListenProps<T>) {
  if (elemente.length === 0) {
    return <p>{leerText}</p>;
  }

  return (
    <ul>
      {elemente.map((element, index) => (
        <li key={index}>{renderElement(element, index)}</li>
      ))}
    </ul>
  );
}

Im Playground ausprobieren

Das Playground unterstützt React und JSX direkt. Du kannst dort Komponenten typisieren und sofort sehen, welche Fehler TypeScript meldet, wenn Props fehlen oder Events falsch typisiert sind. Das ist ein effizienter Weg, neue Muster auszuprobieren, bevor du sie in ein echtes Projekt überträgst.

Fazit

TypeScript macht React-Code robuster und selbstdokumentierend. Props-Interfaces beschreiben den Vertrag einer Komponente. Korrekt typisierte Event-Handler verhindern Tippfehler bei Property-Zugriffen. Wer diese Grundmuster verinnerlicht, profitiert sofort von weniger Laufzeitfehlern und besserer IDE-Unterstützung.

Häufige Fragen

Soll ich React.FC oder direkt function für meine Komponenten verwenden?

Direkt function ist heute die bevorzugte Variante. React.FC fügt implizit children zu den Props hinzu und macht den Rückgabetyp weniger flexibel. Mit der direkten Funktionssyntax hast du mehr Kontrolle und der Code ist klarer.

Wie typisiere ich einen Event-Handler für ein input-Element?

Verwende React.ChangeEvent<HTMLInputElement> für den onChange-Handler. Für Submit-Events bei Formularen ist React.FormEvent<HTMLFormElement> der richtige Typ.

Quellen

  • React TypeScript Cheatsheet (react-typescript-cheatsheet.netlify.app)
Jan-Tristan Rudat

Über die Autorenschaft

Jan-Tristan Rudat

Redakteur typescript-playground.de

Themengebiet: Generationen, Kulturgeschichte, Sternzeichen, Pop-Phänomene rund ums Alter

Mehr über Jan-Tristan Rudat →

Verwandte Artikel

TypeScript Playground nutzen

Sofort im Browser, ohne Anmeldung.

Zum Playground