Can we extract the final character from a string without using the entire alphabet as an enum? Right now, I'm focusing on numeric digits.
I'm somewhat puzzled about why my current approach isn't yielding the correct results.
type Digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';
type GetFirstDigitOfStringLiteralNumber<T extends `${string}${Digit}`> = T extends `${infer D extends Digit}${string}` ? D : never;
type GetLastDigitOfStringLiteralNumber<T extends `${string}${Digit}`> = T extends `${string}${infer D extends Digit}` ? D : never;
// This is accurate
type FirstCharacter = GetFirstDigitOfStringLiteralNumber<"21222">;
// ^? "2"
// This is accurate
type LastCharacter1 = GetLastDigitOfStringLiteralNumber<"12">;
// ^? "2"
// This is incorrect
type LastCharacter2 = GetLastDigitOfStringLiteralNumber<"21222">;
// ^? '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
The issue with `LastChracter2` not functioning correctly surprises me. My assumption is that TypeScript struggles to identify the `${string}` portion accurately and thus stops analyzing static data due to this limitation.
However, it remains unclear why the system doesn't default to returning `never` when unable to match the `Digit` portion to a specific character.
Edit:
Assigning a name to the inferred `${string}` section appears to produce the `never` outcome I originally anticipated, even though no other changes were made:
type Digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';
type GetLastDigitOfStringLiteralNumber<T extends `${string}${Digit}`> = T extends `${infer L extends string}${infer D extends Digit}` ? D : never;
// This works fine
type InferLeading = GetLastDigitOfStringLiteralNumber<"12">;
// ^? "2"
// Why does this fail?
type InferLeading2 = GetLastDigitOfStringLiteralNumber<"112">;
// ^? never