@depup/type-fest 5.4.4-depup.0 → 5.9.0-depup.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/README.md +2 -2
  2. package/changes.json +5 -0
  3. package/index.d.ts +23 -8
  4. package/package.json +17 -11
  5. package/readme.md +98 -64
  6. package/source/absolute.d.ts +52 -0
  7. package/source/all-extend.d.ts +8 -7
  8. package/source/all-union-fields.d.ts +18 -18
  9. package/source/and-all.d.ts +76 -0
  10. package/source/and.d.ts +4 -3
  11. package/source/array-length.d.ts +36 -0
  12. package/source/array-reverse.d.ts +4 -3
  13. package/source/array-splice.d.ts +26 -26
  14. package/source/array-tail.d.ts +4 -4
  15. package/source/camel-case.d.ts +38 -5
  16. package/source/camel-cased-properties-deep.d.ts +11 -4
  17. package/source/camel-cased-properties.d.ts +5 -1
  18. package/source/conditional-keys.d.ts +1 -1
  19. package/source/conditional-pick-deep.d.ts +5 -3
  20. package/source/conditional-pick.d.ts +6 -4
  21. package/source/delimiter-case.d.ts +11 -9
  22. package/source/delimiter-cased-properties-deep.d.ts +8 -1
  23. package/source/delimiter-cased-properties.d.ts +5 -1
  24. package/source/empty-object.d.ts +1 -1
  25. package/source/entries.d.ts +1 -1
  26. package/source/entry.d.ts +1 -1
  27. package/source/exclude-exactly.d.ts +57 -0
  28. package/source/exclude-rest-element.d.ts +4 -4
  29. package/source/exclusify-union.d.ts +4 -4
  30. package/source/extends-strict.d.ts +129 -22
  31. package/source/extract-exactly.d.ts +56 -0
  32. package/source/get.d.ts +1 -1
  33. package/source/greater-than-or-equal.d.ts +34 -1
  34. package/source/greater-than.d.ts +37 -3
  35. package/source/has-optional-keys.d.ts +1 -1
  36. package/source/has-readonly-keys.d.ts +1 -1
  37. package/source/has-required-keys.d.ts +1 -1
  38. package/source/has-writable-keys.d.ts +1 -1
  39. package/source/int-closed-range.d.ts +1 -3
  40. package/source/int-range.d.ts +3 -5
  41. package/source/internal/array.d.ts +8 -15
  42. package/source/internal/keys.d.ts +9 -9
  43. package/source/internal/numeric.d.ts +19 -27
  44. package/source/internal/object.d.ts +44 -6
  45. package/source/internal/string.d.ts +1 -76
  46. package/source/internal/tuple.d.ts +3 -3
  47. package/source/internal/type.d.ts +16 -9
  48. package/source/is-boolean-literal.d.ts +39 -0
  49. package/source/is-equal.d.ts +0 -1
  50. package/source/is-integer.d.ts +8 -8
  51. package/source/is-literal.d.ts +43 -267
  52. package/source/is-numeric-literal.d.ts +50 -0
  53. package/source/is-string-literal.d.ts +72 -0
  54. package/source/is-symbol-literal.d.ts +39 -0
  55. package/source/is-union.d.ts +12 -12
  56. package/source/iterable-element.d.ts +5 -5
  57. package/source/jsonify.d.ts +5 -9
  58. package/source/kebab-case.d.ts +1 -0
  59. package/source/kebab-cased-properties-deep.d.ts +7 -0
  60. package/source/kebab-cased-properties.d.ts +5 -1
  61. package/source/keys-of-union.d.ts +2 -2
  62. package/source/last-array-element.d.ts +66 -13
  63. package/source/less-than-or-equal.d.ts +40 -4
  64. package/source/less-than.d.ts +35 -3
  65. package/source/literal-to-primitive.d.ts +1 -1
  66. package/source/literal-union.d.ts +1 -1
  67. package/source/merge-exclusive.d.ts +3 -3
  68. package/source/merge.d.ts +25 -0
  69. package/source/multidimensional-array.d.ts +1 -1
  70. package/source/multidimensional-readonly-array.d.ts +1 -1
  71. package/source/non-nullable-deep.d.ts +102 -0
  72. package/source/numeric.d.ts +3 -3
  73. package/source/object-merge.d.ts +21 -16
  74. package/source/omit-deep.d.ts +22 -23
  75. package/source/optional.d.ts +31 -0
  76. package/source/or-all.d.ts +73 -0
  77. package/source/or.d.ts +4 -11
  78. package/source/package-json.d.ts +7 -7
  79. package/source/partial-deep.d.ts +3 -1
  80. package/source/pascal-case.d.ts +1 -0
  81. package/source/pascal-cased-properties-deep.d.ts +7 -0
  82. package/source/pascal-cased-properties.d.ts +5 -1
  83. package/source/pick-deep.d.ts +8 -21
  84. package/source/readonly-deep.d.ts +5 -3
  85. package/source/remove-prefix.d.ts +16 -34
  86. package/source/remove-suffix.d.ts +114 -0
  87. package/source/rename-keys.d.ts +163 -0
  88. package/source/replace.d.ts +2 -2
  89. package/source/require-all-or-none.d.ts +5 -5
  90. package/source/require-at-least-one.d.ts +9 -11
  91. package/source/require-exactly-one.d.ts +7 -7
  92. package/source/require-one-or-none.d.ts +5 -5
  93. package/source/required-deep.d.ts +3 -1
  94. package/source/schema.d.ts +16 -8
  95. package/source/screaming-snake-case.d.ts +1 -0
  96. package/source/set-non-nullable-deep.d.ts +8 -4
  97. package/source/set-non-nullable.d.ts +4 -11
  98. package/source/set-optional.d.ts +6 -10
  99. package/source/set-parameter-type.d.ts +2 -2
  100. package/source/set-readonly.d.ts +4 -8
  101. package/source/set-required-deep.d.ts +3 -2
  102. package/source/set-required.d.ts +4 -8
  103. package/source/shared-union-fields-deep.d.ts +5 -4
  104. package/source/shared-union-fields.d.ts +9 -9
  105. package/source/snake-case.d.ts +1 -0
  106. package/source/snake-cased-properties-deep.d.ts +7 -0
  107. package/source/snake-cased-properties.d.ts +5 -1
  108. package/source/some-extend.d.ts +115 -0
  109. package/source/split-on-rest-element.d.ts +6 -4
  110. package/source/split.d.ts +1 -1
  111. package/source/spread.d.ts +1 -5
  112. package/source/string-length.d.ts +38 -0
  113. package/source/string-repeat.d.ts +48 -21
  114. package/source/string-slice.d.ts +1 -1
  115. package/source/string-to-array.d.ts +97 -0
  116. package/source/string-to-number.d.ts +67 -0
  117. package/source/subtract.d.ts +4 -3
  118. package/source/sum.d.ts +5 -4
  119. package/source/tagged.d.ts +5 -7
  120. package/source/tsconfig-json.d.ts +40 -8
  121. package/source/tuple-of.d.ts +42 -8
  122. package/source/typed-array.d.ts +1 -0
  123. package/source/union-length.d.ts +27 -0
  124. package/source/union-member.d.ts +65 -0
  125. package/source/union-to-intersection.d.ts +1 -1
  126. package/source/union-to-tuple.d.ts +10 -19
  127. package/source/unwrap-required.d.ts +37 -0
  128. package/source/words.d.ts +30 -4
  129. package/source/writable.d.ts +15 -19
  130. package/source/xor.d.ts +1 -1
@@ -3,13 +3,14 @@ import type {IsEqual} from '../is-equal.d.ts';
3
3
  import type {KeysOfUnion} from '../keys-of-union.d.ts';
4
4
  import type {RequiredKeysOf} from '../required-keys-of.d.ts';
5
5
  import type {Merge} from '../merge.d.ts';
6
- import type {OptionalKeysOf} from '../optional-keys-of.d.ts';
7
6
  import type {IsAny} from '../is-any.d.ts';
8
7
  import type {If} from '../if.d.ts';
9
8
  import type {IsNever} from '../is-never.d.ts';
9
+ import type {StringToNumber} from '../string-to-number.d.ts';
10
+ import type {Primitive} from '../primitive.d.ts';
10
11
  import type {FilterDefinedKeys, FilterOptionalKeys} from './keys.d.ts';
11
- import type {MapsSetsOrArrays, NonRecursiveType} from './type.d.ts';
12
- import type {StringToNumber, ToString} from './string.d.ts';
12
+ import type {IfNotAnyOrNever, MapsSetsOrArrays, NonRecursiveType} from './type.d.ts';
13
+ import type {ToString} from './string.d.ts';
13
14
 
14
15
  /**
15
16
  Create an object type with the given key `<Key>` and value `<Value>`.
@@ -223,14 +224,23 @@ export type ApplyDefaultOptions<
223
224
  Options extends object,
224
225
  Defaults extends Simplify<Omit<Required<Options>, RequiredKeysOf<Options>> & Partial<Record<RequiredKeysOf<Options>, never>>>,
225
226
  SpecifiedOptions extends Options,
227
+ > =
228
+ _ApplyDefaultOptions<Options, Defaults, SpecifiedOptions> extends infer Result extends Required<Options> // `extends Required<Options>` ensures that `ApplyDefaultOptions<SomeOption, ...>` is always assignable to `Required<SomeOption>`
229
+ ? Result
230
+ : never;
231
+
232
+ type _ApplyDefaultOptions<
233
+ Options,
234
+ Defaults,
235
+ SpecifiedOptions,
226
236
  > =
227
237
  If<IsAny<SpecifiedOptions>, Defaults,
228
238
  If<IsNever<SpecifiedOptions>, Defaults,
229
- Simplify<Merge<Defaults, {
239
+ Merge<Defaults, {
230
240
  [Key in keyof SpecifiedOptions
231
- as Key extends OptionalKeysOf<Options> ? undefined extends SpecifiedOptions[Key] ? never : Key : Key
241
+ as undefined extends Required<Options>[Key & keyof Options] ? Key : undefined extends SpecifiedOptions[Key] ? never : Key
232
242
  ]: SpecifiedOptions[Key]
233
- }> & Required<Options>>>>; // `& Required<Options>` ensures that `ApplyDefaultOptions<SomeOption, ...>` is always assignable to `Required<SomeOption>`
243
+ }>>>;
234
244
 
235
245
  /**
236
246
  Collapses literal types in a union into their corresponding primitive types, when possible. For example, `CollapseLiterals<'foo' | 'bar' | (string & {})>` returns `string`.
@@ -265,6 +275,34 @@ export type CollapseLiterals<T> = {} extends T
265
275
  ? U
266
276
  : T;
267
277
 
278
+ /**
279
+ Returns the base type of a branded type.
280
+
281
+ @example
282
+ ```
283
+ type Brand = {readonly __brand: unique symbol};
284
+
285
+ type A = UnwrapBrand<string & Brand>;
286
+ //=> string
287
+
288
+ type B = UnwrapBrand<number & Brand>;
289
+ //=> number
290
+
291
+ type C = UnwrapBrand<PropertyKey & Brand>;
292
+ //=> PropertyKey
293
+
294
+ type D = UnwrapBrand<(1 | 200n | 'foo' | 'bar') & Brand>;
295
+ //=> 1 | 200n | 'foo' | 'bar'
296
+ ```
297
+ */
298
+ export type UnwrapBrand<T> = IfNotAnyOrNever<T, {ifNot: _UnwrapBrand<T, Primitive>}>;
299
+
300
+ type _UnwrapBrand<T, Base> = T extends Primitive
301
+ ? T extends infer U & Pick<T, Exclude<keyof T, KeysOfUnion<Base>>>
302
+ ? U
303
+ : T
304
+ : T;
305
+
268
306
  /**
269
307
  Normalize keys by including string and number representations wherever applicable.
270
308
 
@@ -1,6 +1,6 @@
1
1
  import type {TupleOf} from '../tuple-of.d.ts';
2
- import type {NegativeInfinity, PositiveInfinity} from '../numeric.d.ts';
3
2
  import type {Trim} from '../trim.d.ts';
3
+ import type {StringLength} from '../string-length.d.ts';
4
4
  import type {Whitespace} from './characters.d.ts';
5
5
 
6
6
  /**
@@ -10,42 +10,6 @@ Note: This type is not the return type of the `.toString()` function.
10
10
  */
11
11
  export type ToString<T> = T extends string | number ? `${T}` : never;
12
12
 
13
- /**
14
- Converts a numeric string to a number.
15
-
16
- @example
17
- ```
18
- type PositiveInt = StringToNumber<'1234'>;
19
- //=> 1234
20
-
21
- type NegativeInt = StringToNumber<'-1234'>;
22
- //=> -1234
23
-
24
- type PositiveFloat = StringToNumber<'1234.56'>;
25
- //=> 1234.56
26
-
27
- type NegativeFloat = StringToNumber<'-1234.56'>;
28
- //=> -1234.56
29
-
30
- type PositiveInfinity = StringToNumber<'Infinity'>;
31
- //=> Infinity
32
-
33
- type NegativeInfinity = StringToNumber<'-Infinity'>;
34
- //=> -Infinity
35
- ```
36
-
37
- @category String
38
- @category Numeric
39
- @category Template literal
40
- */
41
- export type StringToNumber<S extends string> = S extends `${infer N extends number}`
42
- ? N
43
- : S extends 'Infinity'
44
- ? PositiveInfinity
45
- : S extends '-Infinity'
46
- ? NegativeInfinity
47
- : never;
48
-
49
13
  /**
50
14
  Returns a boolean for whether the given string `S` starts with the given string `SearchString`.
51
15
 
@@ -73,45 +37,6 @@ export type StartsWith<S extends string, SearchString extends string> = string e
73
37
  ? true
74
38
  : false;
75
39
 
76
- /**
77
- Returns an array of the characters of the string.
78
-
79
- @example
80
- ```
81
- type A = StringToArray<'abcde'>;
82
- //=> ['a', 'b', 'c', 'd', 'e']
83
-
84
- type B = StringToArray<string>;
85
- //=> never
86
- ```
87
-
88
- @category String
89
- */
90
- export type StringToArray<S extends string, Result extends string[] = []> = string extends S
91
- ? never
92
- : S extends `${infer F}${infer R}`
93
- ? StringToArray<R, [...Result, F]>
94
- : Result;
95
-
96
- /**
97
- Returns the length of the given string.
98
-
99
- @example
100
- ```
101
- type A = StringLength<'abcde'>;
102
- //=> 5
103
-
104
- type B = StringLength<string>;
105
- //=> never
106
- ```
107
-
108
- @category String
109
- @category Template literal
110
- */
111
- export type StringLength<S extends string> = string extends S
112
- ? never
113
- : StringToArray<S>['length'];
114
-
115
40
  /**
116
41
  Returns a boolean for whether a string is whitespace.
117
42
  */
@@ -23,7 +23,7 @@ type Union = TupleLength<[] | [1, 2, 3] | number[]>;
23
23
  */
24
24
  export type TupleLength<T extends UnknownArray> =
25
25
  // `extends unknown` is used to convert `T` (if `T` is a union type) to
26
- // a [distributive conditionaltype](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#distributive-conditional-types))
26
+ // a [distributive conditional type](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#distributive-conditional-types))
27
27
  T extends unknown
28
28
  ? number extends T['length']
29
29
  ? never // Return never if the given type is an non-flexed-length array like `Array<string>`
@@ -46,8 +46,8 @@ type B = TupleMax<[1, 2, 5, 3, 99, -1]>;
46
46
  ```
47
47
  */
48
48
  export type TupleMax<A extends number[], Result extends number = NegativeInfinity> = number extends A[number]
49
- ? never :
50
- A extends [infer F extends number, ...infer R extends number[]]
49
+ ? never
50
+ : A extends [infer F extends number, ...infer R extends number[]]
51
51
  ? GreaterThan<F, Result> extends true
52
52
  ? TupleMax<R, F>
53
53
  : TupleMax<R, Result>
@@ -1,4 +1,3 @@
1
- import type {If} from '../if.d.ts';
2
1
  import type {IsAny} from '../is-any.d.ts';
3
2
  import type {IsNever} from '../is-never.d.ts';
4
3
  import type {Primitive} from '../primitive.d.ts';
@@ -90,16 +89,16 @@ An if-else-like type that resolves depending on whether the given type is `any`
90
89
 
91
90
  @example
92
91
  ```
93
- // When `T` is a NOT `any` or `never` (like `string`) => Returns `IfNotAnyOrNever` branch
94
- type A = IfNotAnyOrNever<string, 'VALID', 'IS_ANY', 'IS_NEVER'>;
92
+ // When `T` is neither `any` nor `never` (like `string`) => Returns `IfNot` branch
93
+ type A = IfNotAnyOrNever<string, {ifNot: 'VALID'; ifAny: 'IS_ANY'; ifNever: 'IS_NEVER'}>;
95
94
  //=> 'VALID'
96
95
 
97
96
  // When `T` is `any` => Returns `IfAny` branch
98
- type B = IfNotAnyOrNever<any, 'VALID', 'IS_ANY', 'IS_NEVER'>;
97
+ type B = IfNotAnyOrNever<any, {ifNot: 'VALID'; ifAny: 'IS_ANY'; ifNever: 'IS_NEVER'}>;
99
98
  //=> 'IS_ANY'
100
99
 
101
100
  // When `T` is `never` => Returns `IfNever` branch
102
- type C = IfNotAnyOrNever<never, 'VALID', 'IS_ANY', 'IS_NEVER'>;
101
+ type C = IfNotAnyOrNever<never, {ifNot: 'VALID'; ifAny: 'IS_ANY'; ifNever: 'IS_NEVER'}>;
103
102
  //=> 'IS_NEVER'
104
103
  ```
105
104
 
@@ -112,7 +111,7 @@ import type {StringRepeat} from 'type-fest';
112
111
  type NineHundredNinetyNineSpaces = StringRepeat<' ', 999>;
113
112
 
114
113
  // The following implementation is not tail recursive
115
- type TrimLeft<S extends string> = IfNotAnyOrNever<S, S extends ` ${infer R}` ? TrimLeft<R> : S>;
114
+ type TrimLeft<S extends string> = IfNotAnyOrNever<S, {ifNot: S extends ` ${infer R}` ? TrimLeft<R> : S}>;
116
115
 
117
116
  // Hence, instantiations with long strings will fail
118
117
  // @ts-expect-error
@@ -121,7 +120,7 @@ type T1 = TrimLeft<NineHundredNinetyNineSpaces>;
121
120
  // Error: Type instantiation is excessively deep and possibly infinite.
122
121
 
123
122
  // To fix this, move the recursion into a helper type
124
- type TrimLeftOptimised<S extends string> = IfNotAnyOrNever<S, _TrimLeftOptimised<S>>;
123
+ type TrimLeftOptimised<S extends string> = IfNotAnyOrNever<S, {ifNot: _TrimLeftOptimised<S>}>;
125
124
 
126
125
  type _TrimLeftOptimised<S extends string> = S extends ` ${infer R}` ? _TrimLeftOptimised<R> : S;
127
126
 
@@ -129,8 +128,16 @@ type T2 = TrimLeftOptimised<NineHundredNinetyNineSpaces>;
129
128
  //=> ''
130
129
  ```
131
130
  */
132
- export type IfNotAnyOrNever<T, IfNotAnyOrNever, IfAny = any, IfNever = never> =
133
- If<IsAny<T>, IfAny, If<IsNever<T>, IfNever, IfNotAnyOrNever>>;
131
+ export type IfNotAnyOrNever<T, Cases extends {ifNot: unknown; ifAny?: unknown; ifNever?: unknown}> =
132
+ IsAny<T> extends true
133
+ ? 'ifAny' extends keyof Cases
134
+ ? Cases['ifAny']
135
+ : any
136
+ : IsNever<T> extends true
137
+ ? 'ifNever' extends keyof Cases
138
+ ? Cases['ifNever']
139
+ : never
140
+ : Cases['ifNot'];
134
141
 
135
142
  /**
136
143
  Returns a boolean for whether the given type is `any` or `never`.
@@ -0,0 +1,39 @@
1
+ import type {CollapseLiterals, UnwrapBrand} from './internal/object.d.ts';
2
+ import type {IfNotAnyOrNever} from './internal/type.d.ts';
3
+
4
+ /**
5
+ Returns a boolean for whether the given type is a `true` or `false` [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types).
6
+
7
+ @example
8
+ ```
9
+ import type {IsBooleanLiteral} from 'type-fest';
10
+
11
+ type A = IsBooleanLiteral<true>;
12
+ //=> true
13
+
14
+ type B = IsBooleanLiteral<false>;
15
+ //=> true
16
+
17
+ type C = IsBooleanLiteral<boolean>;
18
+ //=> false
19
+
20
+ type D = IsBooleanLiteral<true | false>;
21
+ //=> false
22
+ ```
23
+
24
+ @category Type Guard
25
+ @category Utilities
26
+ */
27
+ export type IsBooleanLiteral<T> = IfNotAnyOrNever<T, {
28
+ ifNot: _IsBooleanLiteral<CollapseLiterals<UnwrapBrand<T>>>;
29
+ ifAny: false;
30
+ ifNever: false;
31
+ }>;
32
+
33
+ type _IsBooleanLiteral<T> = boolean extends T
34
+ ? false
35
+ : T extends boolean
36
+ ? true
37
+ : false;
38
+
39
+ export {};
@@ -1,4 +1,3 @@
1
- import type {IsNever} from './is-never.d.ts';
2
1
  /**
3
2
  Returns a boolean for whether the two given types are equal.
4
3
 
@@ -47,14 +47,14 @@ type J = IsInteger<1e-7>;
47
47
  @category Numeric
48
48
  */
49
49
  export type IsInteger<T> =
50
- T extends bigint
51
- ? true
52
- : T extends number
53
- ? number extends T
54
- ? false
55
- : T extends PositiveInfinity | NegativeInfinity
50
+ T extends bigint
51
+ ? true
52
+ : T extends number
53
+ ? number extends T
56
54
  ? false
57
- : Not<IsFloat<T>>
58
- : false;
55
+ : T extends PositiveInfinity | NegativeInfinity
56
+ ? false
57
+ : Not<IsFloat<T>>
58
+ : false;
59
59
 
60
60
  export {};
@@ -1,270 +1,14 @@
1
- import type {Primitive} from './primitive.d.ts';
2
- import type {_Numeric} from './numeric.d.ts';
3
- import type {CollapseLiterals, IfNotAnyOrNever, IsNotFalse, IsPrimitive} from './internal/index.d.ts';
1
+ import type {IsStringLiteral} from './is-string-literal.d.ts';
2
+ import type {IsNumericLiteral} from './is-numeric-literal.d.ts';
3
+ import type {IsBooleanLiteral} from './is-boolean-literal.d.ts';
4
+ import type {IsSymbolLiteral} from './is-symbol-literal.d.ts';
4
5
  import type {IsNever} from './is-never.d.ts';
5
- import type {TagContainer, UnwrapTagged} from './tagged.d.ts';
6
-
7
- /**
8
- Returns a boolean for whether the given type `T` is the specified `LiteralType`.
9
-
10
- @link https://stackoverflow.com/a/52806744/10292952
11
-
12
- @example
13
- ```
14
- type A = LiteralCheck<1, number>;
15
- //=> true
16
-
17
- type B = LiteralCheck<number, number>;
18
- //=> false
19
-
20
- type C = LiteralCheck<1, string>;
21
- //=> false
22
- ```
23
- */
24
- type LiteralCheck<T, LiteralType extends Primitive> = (
25
- IsNever<T> extends false // Must be wider than `never`
26
- ? [T] extends [LiteralType & infer U] // Remove any branding
27
- ? [U] extends [LiteralType] // Must be narrower than `LiteralType`
28
- ? [LiteralType] extends [U] // Cannot be wider than `LiteralType`
29
- ? false
30
- : true
31
- : false
32
- : false
33
- : false
34
- );
35
-
36
- /**
37
- Returns a boolean for whether the given type `T` is one of the specified literal types in `LiteralUnionType`.
38
-
39
- @example
40
- ```
41
- type A = LiteralChecks<1, Numeric>;
42
- //=> true
43
-
44
- type B = LiteralChecks<1n, Numeric>;
45
- //=> true
46
-
47
- type C = LiteralChecks<bigint, Numeric>;
48
- //=> false
49
- ```
50
- */
51
- type LiteralChecks<T, LiteralUnionType> = (
52
- // Conditional type to force union distribution.
53
- // If `T` is none of the literal types in the union `LiteralUnionType`, then `LiteralCheck<T, LiteralType>` will evaluate to `false` for the whole union.
54
- // If `T` is one of the literal types in the union, it will evaluate to `boolean` (i.e. `true | false`)
55
- IsNotFalse<LiteralUnionType extends Primitive
56
- ? LiteralCheck<T, LiteralUnionType>
57
- : never
58
- >
59
- );
60
-
61
- /**
62
- 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).
63
-
64
- Useful for:
65
- - providing strongly-typed string manipulation functions
66
- - constraining strings to be a string literal
67
- - type utilities, such as when constructing parsers and ASTs
68
-
69
- The implementation of this type is inspired by the trick mentioned in this [StackOverflow answer](https://stackoverflow.com/a/68261113/420747).
70
-
71
- @example
72
- ```
73
- import type {IsStringLiteral} from 'type-fest';
74
-
75
- type CapitalizedString<T extends string> = IsStringLiteral<T> extends true ? Capitalize<T> : string;
76
-
77
- // https://github.com/yankeeinlondon/native-dash/blob/master/src/capitalize.ts
78
- function capitalize<T extends Readonly<string>>(input: T): CapitalizedString<T> {
79
- return (input.slice(0, 1).toUpperCase() + input.slice(1)) as CapitalizedString<T>;
80
- }
81
-
82
- const output = capitalize('hello, world!');
83
- //=> 'Hello, world!'
84
- ```
85
-
86
- @example
87
- ```
88
- // String types with infinite set of possible values return `false`.
89
-
90
- import type {IsStringLiteral} from 'type-fest';
91
-
92
- type AllUppercaseStrings = IsStringLiteral<Uppercase<string>>;
93
- //=> false
94
-
95
- type StringsStartingWithOn = IsStringLiteral<`on${string}`>;
96
- //=> false
97
-
98
- // This behaviour is particularly useful in string manipulation utilities, as infinite string types often require separate handling.
99
-
100
- type Length<S extends string, Counter extends never[] = []> =
101
- IsStringLiteral<S> extends false
102
- ? number // return `number` for infinite string types
103
- : S extends `${string}${infer Tail}`
104
- ? Length<Tail, [...Counter, never]>
105
- : Counter['length'];
106
-
107
- type L1 = Length<Lowercase<string>>;
108
- //=> number
109
-
110
- type L2 = Length<`${number}`>;
111
- //=> number
112
- ```
113
-
114
- @category Type Guard
115
- @category Utilities
116
- */
117
- export type IsStringLiteral<S> = IfNotAnyOrNever<S,
118
- _IsStringLiteral<CollapseLiterals<S extends TagContainer<any> ? UnwrapTagged<S> : S>>,
119
- false, false>;
120
-
121
- export type _IsStringLiteral<S> =
122
- // If `T` is an infinite string type (e.g., `on${string}`), `Record<T, never>` produces an index signature,
123
- // and since `{}` extends index signatures, the result becomes `false`.
124
- S extends string
125
- ? {} extends Record<S, never>
126
- ? false
127
- : true
128
- : false;
129
-
130
- /**
131
- Returns a boolean for whether the given type is a `number` or `bigint` [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types).
132
-
133
- Useful for:
134
- - providing strongly-typed functions when given literal arguments
135
- - type utilities, such as when constructing parsers and ASTs
136
-
137
- @example
138
- ```
139
- import type {IsNumericLiteral, IsStringLiteral} from 'type-fest';
140
-
141
- // https://github.com/inocan-group/inferred-types/blob/master/modules/types/src/boolean-logic/operators/EndsWith.ts
142
- type EndsWith<TValue, TEndsWith extends string> =
143
- TValue extends string
144
- ? IsStringLiteral<TEndsWith> extends true
145
- ? IsStringLiteral<TValue> extends true
146
- ? TValue extends `${string}${TEndsWith}`
147
- ? true
148
- : false
149
- : boolean
150
- : boolean
151
- : TValue extends number
152
- ? IsNumericLiteral<TValue> extends true
153
- ? EndsWith<`${TValue}`, TEndsWith>
154
- : false
155
- : false;
156
-
157
- function endsWith<Input extends string | number, End extends string>(input: Input, end: End) {
158
- return `${input}`.endsWith(end) as EndsWith<Input, End>;
159
- }
160
-
161
- endsWith('abc', 'c');
162
- //=> true
163
-
164
- endsWith(123_456, '456');
165
- //=> true
166
-
167
- const end = '123' as string;
168
-
169
- endsWith('abc123', end);
170
- //=> boolean
171
- ```
172
-
173
- @category Type Guard
174
- @category Utilities
175
- */
176
- export type IsNumericLiteral<T> = LiteralChecks<T, _Numeric>;
177
-
178
- /**
179
- Returns a boolean for whether the given type is a `true` or `false` [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types).
180
-
181
- Useful for:
182
- - providing strongly-typed functions when given literal arguments
183
- - type utilities, such as when constructing parsers and ASTs
184
-
185
- @example
186
- ```
187
- import type {IsBooleanLiteral} from 'type-fest';
188
-
189
- const id = 123;
190
-
191
- type GetId<AsString extends boolean> =
192
- IsBooleanLiteral<AsString> extends true
193
- ? AsString extends true
194
- ? `${typeof id}`
195
- : typeof id
196
- : number | string;
197
-
198
- function getId<AsString extends boolean = false>(options?: {asString: AsString}) {
199
- return (options?.asString ? `${id}` : id) as GetId<AsString>;
200
- }
201
-
202
- const numberId = getId();
203
- //=> 123
204
-
205
- const stringId = getId({asString: true});
206
- //=> '123'
207
-
208
- declare const runtimeBoolean: boolean;
209
- const eitherId = getId({asString: runtimeBoolean});
210
- //=> string | number
211
- ```
212
-
213
- @category Type Guard
214
- @category Utilities
215
- */
216
- export type IsBooleanLiteral<T> = LiteralCheck<T, boolean>;
217
-
218
- /**
219
- Returns a boolean for whether the given type is a `symbol` [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types).
220
-
221
- Useful for:
222
- - providing strongly-typed functions when given literal arguments
223
- - type utilities, such as when constructing parsers and ASTs
224
-
225
- @example
226
- ```
227
- import type {IsSymbolLiteral} from 'type-fest';
228
-
229
- type Get<Object_ extends Record<symbol, number>, Key extends keyof Object_> =
230
- IsSymbolLiteral<Key> extends true
231
- ? Object_[Key]
232
- : number;
233
-
234
- function get<Object_ extends Record<symbol, number>, Key extends keyof Object_>(o: Object_, key: Key) {
235
- return o[key] as Get<Object_, Key>;
236
- }
237
-
238
- const symbolLiteral = Symbol('literal');
239
- let symbolValue = Symbol('value1');
240
- symbolValue = Symbol('value2');
241
-
242
- get({[symbolLiteral]: 1} as const, symbolLiteral);
243
- //=> 1
244
-
245
- get({[symbolValue]: 1} as const, symbolValue);
246
- //=> number
247
- ```
248
-
249
- @category Type Guard
250
- @category Utilities
251
- */
252
- export type IsSymbolLiteral<T> = LiteralCheck<T, symbol>;
253
-
254
- /** Helper type for `IsLiteral`. */
255
- type IsLiteralUnion<T> =
256
- | IsStringLiteral<T>
257
- | IsNumericLiteral<T>
258
- | IsBooleanLiteral<T>
259
- | IsSymbolLiteral<T>;
6
+ import type {IfNotAnyOrNever} from './internal/type.d.ts';
7
+ import type {CollapseLiterals, UnwrapBrand} from './internal/object.d.ts';
260
8
 
261
9
  /**
262
10
  Returns a boolean for whether the given type is a [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types).
263
11
 
264
- Useful for:
265
- - providing strongly-typed functions when given literal arguments
266
- - type utilities, such as when constructing parsers and ASTs
267
-
268
12
  @example
269
13
  ```
270
14
  import type {IsLiteral} from 'type-fest';
@@ -300,16 +44,48 @@ type I = IsLiteral<symbol>;
300
44
  type J = IsLiteral<true>;
301
45
  //=> true
302
46
 
303
- type K = IsLiteral<boolean>;
47
+ type K = IsLiteral<false>;
48
+ //=> true
49
+
50
+ type L = IsLiteral<boolean>;
304
51
  //=> false
52
+
53
+ type M = IsLiteral<1 | 'foo' | false>;
54
+ //=> true
55
+
56
+ type N = IsLiteral<string | number | symbol>;
57
+ //=> false
58
+
59
+ type O = IsLiteral<1000n | string | true>;
60
+ //=> boolean
305
61
  ```
306
62
 
307
63
  @category Type Guard
308
64
  @category Utilities
309
65
  */
310
- export type IsLiteral<T> =
311
- IsPrimitive<T> extends true
312
- ? IsNotFalse<IsLiteralUnion<T>>
313
- : false;
66
+ export type IsLiteral<T> = IfNotAnyOrNever<T, {
67
+ ifNot: _IsLiteral<CollapseLiterals<UnwrapBrand<T>>>;
68
+ ifAny: false;
69
+ ifNever: false;
70
+ }>;
71
+
72
+ type _IsLiteral<T> =
73
+ | (Extract<T, boolean> extends infer Bools
74
+ // We can't instantiate `IsBooleanLiteral` with `never`,
75
+ // because that will add an extraneous `false` to the result if there are no booleans.
76
+ ? IsNever<Bools> extends true
77
+ ? never
78
+ : IsBooleanLiteral<Bools>
79
+ : never)
80
+ | (IsLiteralNonBools<Exclude<T, boolean>>);
81
+
82
+ type IsLiteralNonBools<T> =
83
+ T extends number | bigint
84
+ ? IsNumericLiteral<T>
85
+ : T extends string
86
+ ? IsStringLiteral<T>
87
+ : T extends symbol
88
+ ? IsSymbolLiteral<T>
89
+ : false;
314
90
 
315
91
  export {};