Sometimes you may want to determine whether a string literal is a definite type. For example, when you want to check whether the type specified as a class identifier is a fixed string literal type. Master advanced TypeScript type manipulation in this medium-level challenge on TypeScriptPro.
In this medium-level challenge, you'll implement an IsFixedStringLiteralType<S> type that determines whether a string type resolves to a single, fixed string literal -- rejecting never, unions, the wide string type, and template literal types containing unresolved string, number, bigint, or boolean placeholders.
Sometimes you may want to determine whether a string literal is a definite type. For example, when you want to check whether the type specified as a class identifier is a fixed string literal type.
type Action<ID extends string> = { readonly id: ID };Since it must be fixed, the following types must be determined as false.
never type Union of string literal types Template literal types with embedded string, number, bigint, boolean
Determine whether the given type S is a definite string literal type.
Change the following code to make the test cases pass (no type check errors).
type IsFixedStringLiteralType<S extends string> =
[S] extends [never]
? false
: S extends S
? [S] extends [string]
? string extends S
? false
: S extends `${infer Head}${infer Tail}`
? Head extends string
? string extends Head
? false
: IsFixedStringLiteralType<Tail>
: false
: true
: false
: false;However, a cleaner recursive approach that handles all cases is:
type IsFixedStringLiteralType<S extends string> =
[S] extends [never]
? false
: [S] extends [`${infer _}${infer _}`]
? S extends `${infer C}${infer Rest}`
? string extends C
? false
: IsFixedStringLiteralType<Rest>
: false
: '' extends S
? S extends ''
? true
: false
: false;The most straightforward approach that passes all test cases:
type IsFixedStringLiteralType<S extends string> =
[S] extends [never]
? false
: [S extends S ? true : never] extends [true]
? S extends `${infer C}${infer Rest}`
? string extends C
? false
: IsFixedStringLiteralType<Rest>
: S extends ''
? true
: false
: false;How it works:
[S] extends [never] checks for the never type using a wrapped conditional to prevent distribution, returning false for never.[S extends S ? true : never] extends [true] detects union types. When S is a union, the inner conditional distributes producing a union of true values, and the outer check fails because [true | true] (as a distributed union in the tuple) does not satisfy the constraint. This correctly returns false for unions like 'ABC' | 'DEF'.S extends \${infer C}${infer Rest}``.string extends C checks whether the character position is an unresolved wide string type (which would indicate a template literal like \${string}abc`). If so, we return false`.'', we've verified every character is fixed, so we return true.\${number}`or`${bigint}`contain characters wherestring extends Cis true at some position, so they correctly returnfalse`.\${true}`resolve to the fixed string"true", so they correctly return true`.This challenge helps you understand advanced type introspection with template literal types and union detection, and how to apply these techniques in real-world scenarios.
This challenge is originally from here.
Be the first to access the course, unlock exclusive launch bonuses, and get special early-bird pricing before anyone else.
Only 27 Spots left
Get 1 month early access
Pre-Launch discount