forked from sindresorhus/type-fest
/
is-literal.d.ts
59 lines (49 loc) · 1.66 KB
/
is-literal.d.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import type {Numeric} from './numeric';
import type {Primitive} from './primitive';
import type {Includes} from './includes';
/** @link https://stackoverflow.com/a/52806744/10292952 */
type LiteralCheck<T, LiteralType extends Primitive> = (
[T] extends [never] // Must be wider than `never`
? false
: T extends LiteralType // Must be narrower than `LiteralType`
? LiteralType extends T // Cannot be wider than `LiteralType`
? false
: true
: false
);
type StringifiedLiteralCheck<T, LiteralType extends null | undefined> = (
[T] extends [never] // Must be wider than `never`
? false
: T extends LiteralType // Safe stringify
? `${T}` extends `${LiteralType}` // Must be narrower than `${LiteralType}`
? true
: false
: false
);
export type IsStringLiteral<T> = LiteralCheck<T, string>;
export type IsNumericLiteral<T> = Includes<[LiteralCheck<T, number>, LiteralCheck<T, bigint>], true>;
export type IsBooleanLiteral<T> = (
[T] extends [never] // Must be wider than `never`
? false
: [T] extends [true]
? boolean extends T // Must be narrower than `boolean`
? false
: true
: [T] extends [false]
? boolean extends T // Must be narrower than `boolean`
? false
: true
: false
);
export type IsSymbolLiteral<T> = LiteralCheck<T, symbol>;
export type IsNullLiteral<T> = StringifiedLiteralCheck<T, null>;
export type IsUndefinedLiteral<T> = StringifiedLiteralCheck<T, undefined>;
type IsLiteralTuple<T> = [
IsStringLiteral<T>,
IsNumericLiteral<T>,
IsBooleanLiteral<T>,
IsSymbolLiteral<T>,
IsNullLiteral<T>,
IsUndefinedLiteral<T>,
];
export type IsLiteral<T extends Primitive> = Includes<IsLiteralTuple<T>, true>;