I was trying to explore TypeScript intrinsic Capitalize
utility type and found the description of how it's implemented - it looks like this
type Capitalize<S extends string> = S extends `${infer C}${infer $S}`
? `${Uppercase<C>}${$S}`
: never;
I can't quite get two things from this code:
- How does TS understand that
${infer C}
is the first letter? - What is this
$S
syntax?
Small update.
My question wasn't exactly correct, the code above is not how Capitalize
type is implement in TS, it's from github proposal. Some utility types in TS are implemented intrinsicly, which means they don't exactly use the types but rather JavaScript string runtime functions. It happens due to TypeScript overflows, so far TS doesn't support long iterations very well.
Regarding ${infer C}${infer $S}
it's not explained directly why C
type stores first letter in documentation, but I guess it's just a default behavior for TS when it has not enough references on how to split the word.
Let's check this example
type WordPart<S extends string> = S extends `${infer C}${infer R}`
? `${C}`
: never;
type Part = WordPart<'hello'>;
The result Part
type will be 'h'
cause it's not clear how to split the word. At the same time if we change ${infer C}${infer R}
to ${infer C}l${infer R}
we get 'he'
as a result type, so the TypeScript found the first matching l
and split the word there, the remaining inferred R
type would contain lo
in this case.
CodePudding user response:
How does TS understand that ${infer C} is the first letter?
That is a string literal variable https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html
What is this $S syntax?
That belongs to a name