typescript / expert
Snippet
Tief verschachtelte Eigenschaftspfad-Typauflösung mit nicht-distributiven Bedingungen
Dieses fortgeschrittene Snippet nutzt Template-Literal-Typen und rekursive bedingte Typen, um alle gültigen verschachtelten Punkt-Pfade eines Objekttyps zu generieren. Durch das Einpacken des generischen Typparameters T in ein einelementiges Tupel [T] wird verhindert, dass TypeScript bedingte Typen über Unions verteilt, was eine stabile rekursive Auswertung ohne Beeinträchtigung der Typinferenz garantiert.
snippet.ts
typescript
1
2
3
4
type PathImpl<T, K extends keyof T> = K extends string ? (T[K] extends Record<string, any> ? K | `${K}.${PathImpl<T[K], keyof T[K]>}` : K) : never;type ObjectPath<T> = [T] extends [never] ? never : T extends object ? { [K in keyof T]: PathImpl<T, K> }[keyof T] : never;interface UserProfile { id: string; settings: { theme: 'dark' | 'light'; notifications: { email: boolean } }; }type ValidPaths = ObjectPath<UserProfile>;
Erklärung
1
type PathImpl<T, K extends keyof T> = K extends string ? (T[K] extends Record<string, any> ? K | `${K}.${PathImpl<T[K], keyof T[K]>}` : K) : never;
Baut rekursiv punkt-separierte Eigenschaftspfade mittels Template-Literal-Interpolation auf.
2
type ObjectPath<T> = [T] extends [never] ? never : T extends object ? { [K in keyof T]: PathImpl<T, K> }[keyof T] : never;
Verwendet die Tupel-Hülle [T], um die Distributivität über Unions zu unterdrücken und Pfade in eine Union zu extrahieren.
3
type ValidPaths = ObjectPath<UserProfile>;
Wird zum Union-String-Typ 'id' | 'settings' | 'settings.theme' | 'settings.notifications' | 'settings.notifications.email' aufgelöst.