Back

5 TypeScript Utility Types, die Sie kennen sollten

5 TypeScript Utility Types, die Sie kennen sollten

Das Typsystem von TypeScript entfaltet seine wahre Stärke, wenn Sie Utility Types entdecken – eingebaute Helfer, die bestehende Typen transformieren, ohne sie neu schreiben zu müssen. Falls Sie sich schon einmal dabei ertappt haben, Interfaces zu duplizieren oder mit Typ-Modifikationen zu kämpfen, werden diese fünf essentiellen Utility Types Ihre Art, TypeScript-Code zu schreiben, grundlegend verändern.

Wichtige Erkenntnisse

  • Utility Types transformieren bestehende Typen, ohne sie neu zu schreiben, und reduzieren Code-Duplikation
  • Partial macht alle Properties optional – perfekt für Update-Operationen
  • Required erzwingt alle Properties und stellt vollständige Datenstrukturen sicher
  • Pick und Omit helfen dabei, fokussierte Interfaces zu erstellen, indem sie Properties auswählen oder ausschließen
  • Readonly verhindert versehentliche Mutationen – unverzichtbar für unveränderliche Datenmuster

Was sind TypeScript Utility Types und warum sind sie wichtig

Utility Types sind TypeScripts vorgefertigte generische Typen, die neue Typen durch Transformation bestehender konstruieren. Anstatt manuell Variationen Ihrer Interfaces zu erstellen, ermöglichen Ihnen diese Utilities, neue Typen mit spezifischen Modifikationen abzuleiten – was Ihren Code wartbarer macht und Typ-Duplikation reduziert.

Wir werden fünf fundamentale Utility Types erkunden, die häufige reale Probleme lösen: Partial, Required, Pick, Omit und Readonly. Jeder adressiert spezifische Szenarien, denen Sie täglich in der TypeScript-Entwicklung begegnen.

Partial<T>: Alle Properties in TypeScript optional machen

Der Partial Utility Type transformiert alle Properties eines Typs zu optionalen – perfekt für Update-Operationen, bei denen Sie nur spezifische Felder modifizieren.

Wann Partial für Formular-Updates verwenden

Betrachten Sie ein Benutzerprofil-Update, bei dem Benutzer individuelle Felder ändern können, ohne das gesamte Objekt zu senden:

interface User {
  id: string;
  name: string;
  email: string;
  avatar: string;
  lastLogin: Date;
}

function updateUserProfile(userId: string, updates: Partial<User>) {
  // Nur bereitgestellte Felder aktualisieren
  return api.patch(`/users/${userId}`, updates);
}

// Verwendung - nur E-Mail aktualisieren
updateUserProfile("123", { email: "new@email.com" });

Partial Type Beispiel mit realem Code

React State-Updates profitieren erheblich von Partial:

const [user, setUser] = useState<User>(initialUser);

const updateUser = (updates: Partial<User>) => {
  setUser(prev => ({ ...prev, ...updates }));
};

// Nur spezifische Felder aktualisieren
updateUser({ name: "Jane Doe", avatar: "new-avatar.jpg" });

Required<T>: Alle Properties in TypeScript erzwingen

Required bewirkt das Gegenteil von Partial – es macht alle optionalen Properties verpflichtend und stellt vollständige Datenstrukturen sicher.

Optionale zu Required Properties konvertieren

Dies erweist sich als unbezahlbar für Konfigurationsvalidierung:

interface DatabaseConfig {
  host?: string;
  port?: number;
  username?: string;
  password?: string;
}

// Sicherstellen, dass alle Config-Werte existieren, bevor verbunden wird
type ValidatedConfig = Required<DatabaseConfig>;

function connectDatabase(config: ValidatedConfig) {
  // Alle Properties garantiert vorhanden
  return createConnection(config);
}

Required Type in Aktion

Formular-Übermittlung erfordert oft vollständige Daten:

interface RegistrationForm {
  username?: string;
  email?: string;
  password?: string;
  terms?: boolean;
}

type CompleteRegistration = Required<RegistrationForm>;

function submitRegistration(data: CompleteRegistration) {
  // Alle Felder müssen ausgefüllt sein
  api.post('/register', data);
}

Pick<T, K>: Spezifische Properties aus Typen auswählen

Pick erstellt einen neuen Typ durch Auswahl nur spezifizierter Properties – ideal für die Erstellung fokussierter Interfaces.

Fokussierte Typ-Teilmengen mit Pick erstellen

Extrahieren Sie nur das, was Sie für spezifische Komponenten benötigen:

interface Article {
  id: string;
  title: string;
  content: string;
  author: string;
  publishedAt: Date;
  tags: string[];
}

// Card-Komponente benötigt nur diese Felder
type ArticlePreview = Pick<Article, 'id' | 'title' | 'author'>;

function ArticleCard({ article }: { article: ArticlePreview }) {
  return (
    <div>
      <h3>{article.title}</h3>
      <p>von {article.author}</p>
    </div>
  );
}

Pick vs Omit: Den richtigen Ansatz wählen

Verwenden Sie Pick, wenn Sie wenige Properties benötigen, Omit, wenn Sie wenige Properties ausschließen:

// Pick: Wenn Sie 2-3 Properties von einem großen Typ benötigen
type UserSummary = Pick<User, 'id' | 'name'>;

// Omit: Wenn Sie die meisten Properties außer wenigen benötigen
type PublicUser = Omit<User, 'password'>;

Omit<T, K>: Properties aus TypeScript-Typen ausschließen

Omit erstellt einen Typ durch Ausschluss spezifizierter Properties – perfekt zum Entfernen sensibler oder interner Felder.

Sensible Daten mit Omit entfernen

Schützen Sie sensible Informationen in API-Antworten:

interface UserAccount {
  id: string;
  email: string;
  password: string;
  creditCard: string;
  publicProfile: boolean;
}

// Sensible Felder für öffentliche API entfernen
type PublicUserData = Omit<UserAccount, 'password' | 'creditCard'>;

function getPublicProfile(userId: string): Promise<PublicUserData> {
  return api.get(`/users/${userId}/public`);
}

Omit Utility Type Best Practices

Kombinieren Sie mit anderen Utilities für mächtige Muster:

// Interne Felder entfernen und verbleibende optional machen
type UserUpdatePayload = Partial<Omit<User, 'id' | 'createdAt'>>;

Readonly<T>: Unveränderliche Typen in TypeScript erstellen

Readonly macht alle Properties unveränderlich, verhindert versehentliche Mutationen und erzwingt Datenintegrität.

Versehentliche Mutationen mit Readonly verhindern

Unverzichtbar für State Management und Konfiguration:

interface AppConfig {
  apiEndpoint: string;
  version: string;
  features: string[];
}

type ImmutableConfig = Readonly<AppConfig>;

const config: ImmutableConfig = {
  apiEndpoint: "https://api.example.com",
  version: "1.0.0",
  features: ["auth", "payments"]
};

// TypeScript-Fehler: Cannot assign to 'apiEndpoint' because it is a read-only property
config.apiEndpoint = "https://new-api.com"; // ❌

Readonly Properties und React Props

Stellen Sie sicher, dass Props unverändert bleiben:

type UserCardProps = Readonly<{
  user: User;
  onSelect: (id: string) => void;
}>;

function UserCard({ user, onSelect }: UserCardProps) {
  // Props sind innerhalb der Komponente unveränderlich
  return <div onClick={() => onSelect(user.id)}>{user.name}</div>;
}

Mehrere Utility Types für erweiterte Muster kombinieren

Utility Types werden noch mächtiger, wenn sie kombiniert werden:

interface DatabaseRecord {
  id: string;
  createdAt: Date;
  updatedAt: Date;
  deletedAt?: Date;
  data: Record<string, unknown>;
}

// Typ für neue Datensätze erstellen: keine Zeitstempel, partielle Daten
type NewRecord = Omit<DatabaseRecord, 'id' | 'createdAt' | 'updatedAt'> & {
  data: Partial<DatabaseRecord['data']>;
};

// Update-Typ: alles optional außer ID
type UpdateRecord = Partial<Omit<DatabaseRecord, 'id'>> & Pick<DatabaseRecord, 'id'>;

Fazit

Diese fünf Utility Types – Partial, Required, Pick, Omit und Readonly – bilden das Fundament effektiver TypeScript-Entwicklung. Sie eliminieren repetitive Typ-Definitionen, erzwingen Typsicherheit und machen Ihren Code wartbarer.

Beginnen Sie damit, diese Muster in Ihre Codebasis zu integrieren. Starten Sie mit Partial für Update-Operationen, verwenden Sie Omit zur Erstellung sicherer öffentlicher Interfaces und nutzen Sie Readonly zur Fehlervermeidung. Wenn Sie sich wohler fühlen, kombinieren Sie sie, um ausgeklügelte Typ-Transformationen zu erstellen, die perfekt zu den Bedürfnissen Ihrer Anwendung passen.

Häufig gestellte Fragen

Ja, Sie können Utility Types verschachteln, um komplexe Transformationen zu erstellen. Beispielsweise funktionieren Partial und Omit gut zusammen, um Update-Payloads zu erstellen, die bestimmte Felder ausschließen, während andere optional gemacht werden.

Nein, Utility Types sind reine Compile-Time-Konstrukte. TypeScript entfernt alle Typ-Informationen während der Kompilierung, daher haben Utility Types keinen Laufzeit-Overhead.

Interface-Erweiterung erstellt neue Typen durch Hinzufügung von Properties, während Utility Types bestehende Typen transformieren. Utility Types bieten mehr Flexibilität für die Modifikation von Typen, die Sie nicht kontrollieren, oder die Erstellung von Variationen bestehender Typen.

Ja, TypeScript ermöglicht es Ihnen, benutzerdefinierte Utility Types mit Mapped Types, Conditional Types und Template Literal Types zu erstellen. Beginnen Sie mit eingebauten Utilities und erstellen Sie benutzerdefinierte, wenn Sie wiederkehrende Muster identifizieren.

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.

OpenReplay