Rozwiązanie z komentarzem
Opublikowano 4 września 2026Rozwiązanie
type DeepPartial<T> = { [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K] }
Najczęstsza błędna odpowiedź
type DeepPartial<T> = { [K in keyof T]?: T[K] }
To jest `Partial` i zatrzymuje się na pierwszym poziomie. `{ a: { b: string } }` staje się `{ a?: { b: string } }` — zewnętrzny klucz jest opcjonalny, a `b` pozostaje tak samo wymagane jak było. Głębokość nie bierze się sama z siebie; typ musi o nią poprosić.
Linia po linii
T[K] extends object ? DeepPartial<T[K]> : T[K]Rekurencja mieszka w klauzuli wartości. Wszystko, co ma kształt obiektu, wraca przez `DeepPartial`; prymitywy zwracane są nietknięte i to właśnie kończy schodzenie w głąb.
[K in keyof T]?:`?` trafia na każdy poziom, bo każdy poziom to kolejne wywołanie tego samego typu mapowanego. Jedna reguła, napisana raz, zastosowana aż do dna.
Do zapamiętania
Rekurencyjny typ mapowany to po prostu typ mapowany, który wywołuje sam siebie w pozycji wartości. Warunek, który go zatrzymuje — tutaj „czy to wciąż obiekt?” — znaczy więcej niż sama rekurencja.
