Rozwiązanie z komentarzem
Opublikowano 28 sierpnia 2026Rozwiązanie
type Repeat< S extends string, N extends number, Acc extends unknown[] = [], > = Acc['length'] extends N ? '' : `${S}${Repeat<S, N, [...Acc, unknown]>}`
Najczęstsza błędna odpowiedź
type Repeat< S extends string, N extends number, Acc extends unknown[] = [], > = Acc['length'] extends N ? S : `${S}${Repeat<S, N, [...Acc, unknown]>}`
Przypadek bazowy wypuszcza jedną kopię za dużo. Zwrócenie S, gdy licznik jest pełny, sprawia, że krok kończący też dokłada swoje, więc Repeat<"ab", 3> daje cztery kopie — a Repeat<"x", 0> zwraca "x", choć powinien nie zwrócić nic.
Linia po linii
Acc['length'] extends N ? ''Przypadek bazowy musi być *elementem neutralnym* budowanej operacji. Dla konkatenacji jest nim pusty łańcuch — dokładnie tak jak
[]przy budowaniu krotki i0przy dodawaniu liczb.[...Acc, unknown]Akumulator trzyma
unknown, bo jego zawartość nie ma znaczenia — odczytywana jest tylko długość. To licznik kresek, a nie kolekcja.
Do zapamiętania
Gdy pętla na typach myli się o jeden, patrz na to, co zwraca przypadek bazowy, a nie na krok rekurencyjny. Gałąź kończąca powinna dokładać element neutralny, a nie kolejną kopię ładunku.

