IsFixedStringLiteralType
Less than 1 minuteTC-Medium
IsFixedStringLiteralType
Problem
Determine if a type is a fixed (non-template) string literal type.
type T0 = IsFixedStringLiteralType<'foo'> // true
type T1 = IsFixedStringLiteralType<string> // false
type T2 = IsFixedStringLiteralType<`${string}`> // false (template literal = not fixed)
type T3 = IsFixedStringLiteralType<`foo`> // true (no interpolation = fixed)
type T4 = IsFixedStringLiteralType<'foo' | 'bar'> // boolean (distributes)
type T5 = IsFixedStringLiteralType<number> // falseSolution
type IsFixedStringLiteralType<T extends string> =
string extends T
? false
: T extends `${infer _Head}${infer _Tail}`
? _Head extends string
? _Tail extends ''
? true
: IsFixedStringLiteralType<_Tail>
: false
: T extends ''
? true
: falseA simpler approach:
type IsFixedStringLiteralType<T extends string> =
[T] extends [never]
? false
: string extends T
? false
: T extends `${string & {}}${infer _}`
? false
: trueMost concise approach:
type IsFixedStringLiteralType<T extends string> =
string extends T ? false : `_${T}` extends `_${string & {}}` ? false : trueHow it works:
string extends T— ifTis the broadstringtype, returnfalse.- Template literal types with interpolated
string(like`${string}`) are not fixed literals. - A plain string literal like
'foo'is narrower thanstring, and concatenating a prefix_doesn't produce a template-literal-type — so the check distinguishes fixed from template literals.
Key Takeaways
string extends Tchecks ifTis the widenedstringtype (not a literal).- Template literal types with open interpolations (
${string}) are structurally distinct from fixed literals. string & {}is a trick to get a non-wideningstringtype for pattern matching purposes.
