Einleitung: Warum wird das so oft gesucht?
\n\nJeder Entwickler, der von JavaScript zu TypeScript wechselt oder einfach in dieser Sprache schreibt, stößt früher oder später auf das Problem: Wie legt man korrekt einen Standardwert für ein Objekt fest, das an eine Funktion übergeben wird? Auf Stack Overflow hat diese Frage tausende Aufrufe und Dutzende Antworten erhalten. Warum? Weil eine scheinbar einfache Aufgabe – „Wenn kein Objekt übergeben wird, verwende ein leeres Objekt“ – in TypeScript zu einer regelrechten Herausforderung mit Typen, Interfaces und Destrukturierung wird.
\n\nIn diesem Artikel werden wir alle möglichen Methoden durchgehen, von den einfachsten bis zu den fortgeschrittensten, mit Codebeispielen und Erklärungen. Sie erfahren, wie Sie Standardwerte für ein TypeScript-Objekt einrichten, das als Argument übergeben wird, und typische Fehler vermeiden. Los geht's!
\n\nDas Problem: Was ist am üblichen Ansatz falsch?
\n\nAngenommen, wir haben eine Funktion, die ein Objekt mit Einstellungen akzeptiert:
\n\nfunction createUser(config: { name?: string; age?: number }) {\n // ...\n}\n\ncreateUser(); // Fehler! Ein Argument wird benötigt\n\n\nIn JavaScript könnten wir einfach function createUser(config = {}) schreiben und die Sache wäre erledigt. Aber in TypeScript funktioniert dieser Trick nicht: Der Compiler wird sich über Typenkonflikte beschweren. Warum? Weil das leere Objekt {} nicht dem Interface { name?: string; age?: number } entspricht – es hat diese Eigenschaften einfach nicht.
Und hier beginnt das Interessante. Lassen Sie uns alle Lösungswege durchgehen.
\n\nMethode 1: Destrukturierung mit Zuweisung von Standardwerten
\n\nDie eleganteste und beliebteste Methode ist die Verwendung der Destrukturierung direkt in den Funktionsparametern. Sie extrahieren die Eigenschaften des Objekts und weisen ihnen sofort Standardwerte zu:
\n\nfunction createUser({ name = "Gast", age = 18 }: { name?: string; age?: number } = {}) {\n console.log(`Benutzer erstellt: ${name}, Alter: ${age}`);\n}\n\ncreateUser(); // "Benutzer erstellt: Gast, Alter: 18"\ncreateUser({ name: "Anna" }); // "Benutzer erstellt: Anna, Alter: 18"\ncreateUser({ age: 25 }); // "Benutzer erstellt: Gast, Alter: 25"\n\n\nBeachten Sie das = {} am Ende. Dies ist der Standardwert für das Objekt selbst. Wenn Sie kein Argument übergeben, verwendet TypeScript ein leeres Objekt, und die Destrukturierung setzt die Standardwerte für jede Eigenschaft ein.
Vorteile: sauber, prägnant, funktioniert einwandfrei.
\nNachteile: Der Typ muss für jede Eigenschaft explizit angegeben werden.
Methode 2: Verwendung eines Interfaces mit Partial
\n\nWenn Ihr Objekt groß ist, ist es schlechter Stil, alle Typen in den Parametern zu beschreiben. Lagern Sie das Interface aus und verwenden Sie Partial<T>:
interface UserConfig {\n name: string;\n age: number;\n email: string;\n isAdmin: boolean;\n}\n\nfunction createUser(config: Partial<UserConfig> = {}) {\n const defaults: UserConfig = {\n name: "Gast",\n age: 18,\n email: "noemail@example.com",\n isAdmin: false\n };\n \n const mergedConfig = { ...defaults, ...config };\n console.log(mergedConfig);\n}\n\ncreateUser({ name: "Ivan" });\n// { name: "Ivan", age: 18, email: "noemail@example.com", isAdmin: false }\n\n\nHier macht Partial<UserConfig> alle Eigenschaften optional. Innerhalb der Funktion führen wir die Standardwerte mit den übergebenen Werten zusammen. Funktioniert hervorragend, erfordert aber manuelles Zusammenführen.
Methode 3: Klassischer Ansatz mit Überprüfung
\n\nManchmal ist mehr Kontrolle erforderlich. Zum Beispiel, wenn Sie einen Standardwert nur für undefined, aber nicht für null festlegen möchten. Verwenden Sie die gute alte if-Abfrage:
function createUser(config?: UserConfig) {\n const name = config?.name ?? "Gast";\n const age = config?.age ?? 18;\n const email = config?.email ?? "noemail@example.com";\n \n console.log({ name, age, email });\n}\n\ncreateUser();