9

Is it possible to build a repeat with template literal types? For example:

type Hex = 'a' | 'b' | 'c'| ...; type Id = `${Hex}${Hex}...` // Here I want to say Id is N hex long. 
1
  • What type exactly are you expect? Coult you please add it literally? Because ${Hex}${Hex}... produces all pair of union type Commented Dec 17, 2020 at 8:38

1 Answer 1

10

In principle, this is possible with recursive conditional types in TS 4.1:

type Decrement = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] type RepeatString<S extends string, N extends number> = N extends 1 ? S : `${S}${RepeatString<S, Decrement[N]>}` 
type T11 = Decrement[5] // 4 type T12 = RepeatString<"foo", 3> // "foofoofoo" type T13 = RepeatString<Hex, 3> // "aaa" | "aab" | ... | "ccb" | "ccc" 

Beware of the following limitation:

Beware that the cross product distribution of union types can quickly escalate into very large and costly types. Also note that union types are limited to less than 100,000 constituents [.] (my emphasis)

For example, with Hex2 being 'a' | 'b' | ... | 'i' | 'j' (10 union parts), type T14 = RepeatString<Hex2, 5> will trigger following error (10*10*10*10*10 permutations):

Expression produces a union type that is too complex to represent.(2590)

In this case, it is needed to reduce the number of union parts, like finding bigger chunks of strings instead of atomic chars.

Alternative

type RepeatStringAlt<S extends string, N extends number> = RepeatStringAltRec<S, TupleOf<unknown, N>> type RepeatStringAltRec<S extends string, T extends unknown[]> = T["length"] extends 1 ? S : `${S}${RepeatStringAltRec<S, DropFirst<T>>}` type TupleOf<T, N extends number> = N extends N ? number extends N ? T[] : _TupleOf<T, N, []> : never; type _TupleOf<T, N extends number, R extends unknown[]> = R['length'] extends N ? R : _TupleOf<T, N, [T, ...R]>; type DropFirst<T extends readonly unknown[]> = T extends readonly [any?, ...infer U] ? U : [...T]; type T23 = RepeatStringAlt<"foo", 3> // "foofoofoo" 

This gets rid of counting the number range manually with Decrement.

Live code playground

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. It is possible to distribute over generic type, preventing the cross product problem: stackoverflow.com/a/63401962/4592648

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.