Głębokość i ograniczenia rekurencji
Poznaj ograniczenia głębokości rekurencji w TypeScript
Głębokość i ograniczenia rekurencji to bezpłatna lekcja TypeScript Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej TypeScript Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs TypeScript Academy zawiera 4 lekcji w sumie.
TypeScript ma limity rekurencji
Typy rekurencyjne są potężne, ale narzędzie sprawdzające typy ogranicza głębokość ich instancjowania. Po przekroczeniu limitu pojawia się błąd głębokości.
// Excessively deep recursive types can produce:
// "Type instantiation is excessively deep and possibly infinite."Skąd biorą się błędy głębokości
Typy warunkowe, które rekurują bez wyraźnego, zmniejszającego się przypadku bazowego, mogą wymknąć się spod kontroli, zwłaszcza w połączeniu z dużymi uniami lub budowaniem krotek.
type Repeat<N extends number, Acc extends unknown[] = []> =
Acc["length"] extends N ? Acc : Repeat<N, [...Acc, unknown]>;
// Large N can exceed the instantiation depth.
type Five = Repeat<5>;Bezpieczna rekurencja z ograniczeniem
Rekurencja powinna być płytka i mieć ograniczenie. Zbudowanie niewielkiej krotki jest bezpieczne, a przypadek bazowy Acc["length"] extends N szybko ją zatrzymuje.
type Tuple<N extends number, Acc extends unknown[] = []> =
Acc["length"] extends N ? Acc : Tuple<N, [...Acc, unknown]>;
type Three = Tuple<3>; // [unknown, unknown, unknown]
const t: Three = [1, 2, 3];
console.log(t.length);Wzorce rekurencji ogonowej
TypeScript optymalizuje niektóre warunkowe typy rekurencyjne ogonowo, przekazując akumulator, co pozwala na głębszą rekurencję niż naiwne zagnieżdżanie.
type Reverse<T extends unknown[], Acc extends unknown[] = []> =
T extends [infer Head, ...infer Tail]
? Reverse<Tail, [Head, ...Acc]>
: Acc;
type R = Reverse<[1, 2, 3]>; // [3, 2, 1]
const r: R = [3, 2, 1];
console.log(r);Dlaczego akumulatory pomagają
Przekazywanie wyników w akumulatorze utrzymuje rekurencję w pozycji ogonowej, dzięki czemu TypeScript może rozwijać ją wydajniej niż głęboko zagnieżdżone typy warunkowe.
type Join<T extends string[], Acc extends string = ""> =
T extends [infer H extends string, ...infer R extends string[]]
? Join<R, Acc extends "" ? H : Acc>
: Acc;
type First = Join<["a", "b", "c"]>; // "a"
const f: First = "a";
console.log(f);Unikanie rekurencji nieogonowej
Umieszczenie wywołania rekurencyjnego wewnątrz innej operacji na typie przerywa pozycję ogonową i może szybciej doprowadzić do przekroczenia limitów. Zamiast tego należy przechowywać stan w akumulatorze.
// Non-tail (can be costly): builds nesting around the recursive call
// type Bad<T> = T extends [infer H, ...infer R] ? [H, ...Bad<R>] : [];
// Tail-friendly alternative uses an accumulator parameter.
console.log("prefer accumulators");Jawne ograniczanie głębokości
Należy dodać licznik głębokości, aby typ kończył działanie po ustalonej liczbie poziomów, zamieniając kompletność na gwarantowane zakończenie.
type Flatten<T, Depth extends unknown[] = []> =
Depth["length"] extends 5
? T
: T extends (infer U)[]
? Flatten<U, [...Depth, unknown]>
: T;
type X = Flatten<number[][]>; // number
const x: X = 7;
console.log(x);Praktyczna głębokość zwykle wystarcza
Codzienne typy rekurencyjne, listy wiązane, drzewa i JSON zwykle nigdy nie osiągają limitu, ponieważ instancjonowane dane są płytkie. Limity dotyczą głównie intensywnych obliczeń na poziomie typów.
type Json = string | number | boolean | null | Json[] | { [k: string]: Json };
const v: Json = { a: { b: { c: 1 } } }; // fine, shallow
console.log(v);Rozpoznawanie komunikatu o błędzie
Gdy pojawi się komunikat "excessively deep and possibly infinite", należy poszukać brakującego przypadku bazowego, akumulatora w pozycji nieogonowej albo zbyt dużych danych wejściowych.
// Fixes: add/tighten the base case, switch to tail recursion,
// reduce input size, or cap with a depth counter.
console.log("check base case and tail position");Rekurencja w czasie działania to osobna kwestia
Te limity dotyczą rekurencji na poziomie typów. Zwykłe funkcje rekurencyjne operujące na typach rekurencyjnych działają w czasie wykonania i są ograniczone tylko rozmiarem stosu wywołań.
type TreeNode<T> = { value: T; children: TreeNode<T>[] };
function count<T>(n: TreeNode<T>): number {
return 1 + n.children.reduce((a, c) => a + count(c), 0);
}
console.log(count({ value: 1, children: [{ value: 2, children: [] }] }));Projektowanie z uwzględnieniem limitów
Należy preferować płytkie dane, wzorce rekurencji ogonowej z akumulatorami oraz jawne ograniczenia głębokości. Dzięki tym zasadom w prawdziwym kodzie rzadko napotkają Państwo ten limit.
type Length<T extends unknown[]> = T["length"];
type N = Length<[1, 2, 3]>; // 3
const n: N = 3;
console.log(n);Szybkie sprawdzenie: limity rekurencji
Proszę sprawdzić swoją wiedzę na temat głębokości rekurencji i limitów.
Podsumowanie: głębokość i limity rekurencji
Dowiedzieli się Państwo, że TypeScript ogranicza głębokość rekurencji na poziomie typów, że pomagają wzorce rekurencji ogonowej z akumulatorami i jawne ograniczenia głębokości oraz że codzienne dane rekurencyjne rzadko osiągają ten limit.
type Reverse<T extends unknown[], Acc extends unknown[] = []> =
T extends [infer H, ...infer R] ? Reverse<R, [H, ...Acc]> : Acc;
const r: Reverse<[1, 2]> = [2, 1];
console.log(r);Często zadawane pytania
Czy lekcja „Głębokość i ograniczenia rekurencji” jest bezpłatna?
Tak — pełny tekst „Głębokość i ograniczenia rekurencji” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu TypeScript Academy, przejdź na CoddyKit PRO. Kurs TypeScript Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Głębokość i ograniczenia rekurencji”?
Poznaj ograniczenia głębokości rekurencji w TypeScript Ćwiczysz TypeScript Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć TypeScript Academy?
Nie wymagamy żadnego doświadczenia. TypeScript Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.
Ile czasu zajmuje lekcja „Głębokość i ograniczenia rekurencji”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji TypeScript Academy?
Tak. Każda lekcja TypeScript Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Rekurencyjne definicje typów
- Typowanie struktur drzewiastych
- Typy wartości JSON
- Głębokość i ograniczenia rekurencji