import type {CollapseLiterals, UnwrapBrand} from './internal/object.d.ts'; import type {IfNotAnyOrNever} from './internal/type.d.ts'; /** Returns a boolean for whether the given type is a `string` [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types). The implementation of this type is inspired by the trick mentioned in this [StackOverflow answer](https://stackoverflow.com/a/68261113/420747). @example ``` import type {IsStringLiteral} from 'type-fest'; type A = IsStringLiteral<'foo'>; //=> true type B = IsStringLiteral; //=> false // String types with infinite set of possible values return `false` type C = IsStringLiteral<`on${string}`>; //=> false type D = IsStringLiteral>; //=> false type E = IsStringLiteral<'foo' | 'bar' | 'baz'>; //=> true type F = IsStringLiteral<'sm' | 'md' | 'lg' | `${number}px`>; //=> boolean ``` @example ``` import type {IsStringLiteral} from 'type-fest'; type StringLength = IsStringLiteral extends true ? S extends `${string}${infer Tail}` ? StringLength : Counter['length'] : number; // return `number` for non-literal string types type L1 = StringLength<'foobar'>; //=> 6 type L2 = StringLength>; //=> number type L3 = StringLength<`${number}`>; //=> number ``` @category Type Guard @category Utilities */ export type IsStringLiteral = IfNotAnyOrNever>>; ifAny: false; ifNever: false; }>; type _IsStringLiteral = // If `S` is an infinite string type (e.g., `on${string}`), `Record` produces an index signature, // and since `{}` extends index signatures, the result becomes `false`. S extends string ? {} extends Record ? false : true : false; export {};