type IsUnion<T, U = T> = [T] extends [never]
? false
: T extends T
? [U] extends [T]
? false
: true
: never;
type IsFixedStringLiteralType<S extends string> = IsUnion<S> extends true
? false
: { [P: string]: unknown } extends {
[P in S]: unknown;
}
? false
: true;
Solution by yukicountry #34493
type IsFixedStringLiteralType<S extends string> = {} extends Record<S, 1> ? false : Equal<[S], S extends unknown ? [S] : never>
Solution by ahmed-omegup #33984
type IsNumOrBool<S extends string> = S extends `${infer _ extends number}${any}` ? true :
S extends `${infer _ extends bigint}${any}` ? true :
S extends `${infer F extends boolean}${any}` ? F extends true | false ? false : true : false
type IsConst<S extends string> = S extends '' ? true :
IsNumOrBool<S> extends false ? S extends `${infer F}${infer Rest}` ? string extends F ? false : `${string & {}}` extends F ? false : IsConst<Rest> : false : false
type IsUnion<S extends string, T = S> = S extends T ? [T] extends [S] ? false : true : never
type IsFixedStringLiteralType<S extends string> = [S] extends [never] ? false : IsUnion<S> extends false ? IsConst<S> : false
Solution by moonshadow-miao #33926
// to determine if a string S is a definite string literal type.
type IsFixedStringLiteralType<S> = [S] extends [AsUnion<S> | AsWildcard<S>] ? false : true
// to determine if S is a union type or should evaluate to never
type AsUnion<S, U = S> = U extends U ? Exclude<S, U> : U
// to check for embedded wildcards in S or should evaluate to never
type AsWildcard<S>
= S extends `${WildcardConstraint<infer _>}${any}` ? S
: S extends `${any}${infer R}` ? [AsWildcard<R>] extends [never] ? never : S
: S extends '' ? never : S // if the string is not empty but does not match the initial template split
// To match a wildcard `${number}`, `${string}`, etc
type WildcardConstraint<C extends string> = `${any}` extends C ? C : never
Solution by teamchong #32985
// your answers
import type { Equal, NotEqual } from '@type-challenges/utils'
type IsNever<T> = [T] extends [never] ? true : false;
type IsUnion<T> = NotEqual<[T] & T, (T extends T ? [T] : never) & T>;
type IsFixedStringLiteralType<S extends string> = true extends
| IsNever<S>
| IsUnion<S>
| Equal<S, string>
? false
: S extends `${infer First}${infer Rest}`
? true extends
| Equal<First, string>
| Equal<First, `${string & {}}`>
| Equal<First, `${number}`>
| Equal<First, `${number & {}}`>
| Equal<First, `${bigint}`>
| Equal<First, `${bigint & {}}`>
| Equal<First, `${any}`>
? false
: IsFixedStringLiteralType<Rest>
: true;
Solution by wubrafiq807 #32614
type IsUnion<T, U = T> = [T] extends [never] ? false : T extends T ? [U] extends [T] ? false : true : false
type IsEmbedded<T> = Equal<T, string> extends true
? true
: Equal<T, `${bigint}`> extends true
? true
: Equal<T, `${number}`> extends true
? true
: Equal<T, `${boolean}`> extends true
? true
: Equal<T, `${string & {}}`> extends true // Additional, `${number & {}}` etc.
? true
: false
type IsFixedStringLiteralType<S extends string> =
[S] extends [never]
? false // 1. never type
: IsUnion<S> extends true
? false // 2. union
: S extends `${infer F}${ infer Rest extends string}`
? IsEmbedded<F> extends true // 3. embedded types
? false
: Rest extends ''
? true
: IsFixedStringLiteralType<Rest>
: false
Solution by lvjiaxuan #31978
type SingleCheck<S> = S extends ''
? true
: S extends `${infer C}${infer T}`
? '0' | '1' extends C
? false
: SingleCheck<T>
: false;
type IsFixedStringLiteralType<S extends string, T = S> = [S] extends [never]
? false
: S extends unknown
? [T] extends [S]
? SingleCheck<S>
: false
: false;
Solution by alexandroppolus #31666
import type { Equal, NotEqual } from '@type-challenges/utils'
type IsNever<T> = [T] extends [never] ? true : false;
type IsUnion<T> = NotEqual<[T] & T, (T extends T ? [T] : never) & T>;
type IsFixedStringLiteralType<S extends string> = true extends
| IsNever<S>
| IsUnion<S>
| Equal<S, string>
? false
: S extends `${infer First}${infer Rest}`
? true extends
| Equal<First, string>
| Equal<First, `${string & {}}`>
| Equal<First, `${number}`>
| Equal<First, `${number & {}}`>
| Equal<First, `${bigint}`>
| Equal<First, `${bigint & {}}`>
| Equal<First, `${any}`>
? false
: IsFixedStringLiteralType<Rest>
: true;
Solution by sugoroku-y #31481