Zbyt głęboka instancjacja
Type instantiation is excessively deep and possibly infinite.Własne słowa kompilatora. Nietłumaczone — to ten ciąg, który wkleiłeś w wyszukiwarkę.
Typ rekurencyjny zaszedł dalej, niż kompilator jest gotów podążyć — zwykle około pięćdziesięciu poziomów, i niemal zawsze dlatego, że rekurencja liczy, zamiast się kurczyć.
Odtworzenie
type Repeat<S extends string, N extends number, A extends unknown[] = []> = A['length'] extends N ? S : Repeat<`${S}x`, N, [...A, unknown]> type Long = Repeat<'a', 1000>
Build potwierdza, że to emituje dokładnie ten kod.
Dlaczego kompilator tak mówi
TypeScript ma twardy sufit na to, ile razy typ może się zinstancjonować, bo typ rekurencyjny bez końca zawiesiłby kompilator, zamiast po prostu zawieść. Ten limit nie jest błędem i nie da się go podkręcić. Osiągnięcie go znaczy, że rekurencja wykonuje arytmetykę — krok na jednostkę — a jedyną skalującą się naprawą jest sprawienie, by każdy krok usuwał więcej pracy, niż dokłada.
Naprawy
- 01
type Repeat<S extends string, N extends number, A extends unknown[] = []> = A['length'] extends N ? S : Repeat<`${S}x`, N, [...A, unknown]> type Short = Repeat<'a', 12>
Trzymaj się pod sufitem. Jeśli wejście jest naprawdę małe — ścieżka o czterech segmentach, krotka o dziesięciu elementach — licząca rekurencja jest w porządku, a uczciwą naprawą jest przestać prosić ją o tysiąc.
- 02
type Repeat<S extends string, N extends number> = N extends 0 ? '' : string type Wide = Repeat<'a', 1000>
Albo zrezygnuj z precyzji. Typ, który dla czegokolwiek dużego zwraca `string`, jest mniej informatywny i nieskończenie tańszy, a dla wartości, której nikt nie czyta znak po znaku, to zwykle właściwy kompromis.
Wniosek
Ten błąd niemal nigdy nie rozwiązuje się przez przebudowę rekurencji. Rozwiązuje się go, chcąc mniej: mniejszego wejścia albo mniej dokładnej odpowiedzi.