@depup/type-fest 5.5.0-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 (117) hide show
  1. package/README.md +2 -2
  2. package/changes.json +1 -1
  3. package/index.d.ts +16 -8
  4. package/package.json +8 -6
  5. package/readme.md +85 -61
  6. package/source/absolute.d.ts +52 -0
  7. package/source/all-extend.d.ts +6 -4
  8. package/source/all-union-fields.d.ts +18 -18
  9. package/source/and.d.ts +1 -1
  10. package/source/array-reverse.d.ts +4 -3
  11. package/source/array-splice.d.ts +24 -24
  12. package/source/array-tail.d.ts +4 -4
  13. package/source/camel-case.d.ts +38 -5
  14. package/source/camel-cased-properties-deep.d.ts +11 -4
  15. package/source/camel-cased-properties.d.ts +5 -1
  16. package/source/conditional-keys.d.ts +1 -1
  17. package/source/delimiter-case.d.ts +11 -9
  18. package/source/delimiter-cased-properties-deep.d.ts +8 -1
  19. package/source/delimiter-cased-properties.d.ts +5 -1
  20. package/source/empty-object.d.ts +1 -1
  21. package/source/entries.d.ts +1 -1
  22. package/source/entry.d.ts +1 -1
  23. package/source/exclude-exactly.d.ts +11 -11
  24. package/source/exclude-rest-element.d.ts +4 -4
  25. package/source/exclusify-union.d.ts +4 -4
  26. package/source/extends-strict.d.ts +129 -22
  27. package/source/extract-exactly.d.ts +56 -0
  28. package/source/get.d.ts +1 -1
  29. package/source/greater-than.d.ts +3 -2
  30. package/source/has-optional-keys.d.ts +1 -1
  31. package/source/has-readonly-keys.d.ts +1 -1
  32. package/source/has-required-keys.d.ts +1 -1
  33. package/source/has-writable-keys.d.ts +1 -1
  34. package/source/int-closed-range.d.ts +1 -3
  35. package/source/int-range.d.ts +3 -5
  36. package/source/internal/array.d.ts +8 -8
  37. package/source/internal/keys.d.ts +9 -9
  38. package/source/internal/numeric.d.ts +19 -27
  39. package/source/internal/object.d.ts +44 -6
  40. package/source/internal/string.d.ts +1 -76
  41. package/source/internal/tuple.d.ts +2 -2
  42. package/source/internal/type.d.ts +16 -10
  43. package/source/is-boolean-literal.d.ts +39 -0
  44. package/source/is-integer.d.ts +8 -8
  45. package/source/is-literal.d.ts +43 -267
  46. package/source/is-numeric-literal.d.ts +50 -0
  47. package/source/is-string-literal.d.ts +72 -0
  48. package/source/is-symbol-literal.d.ts +39 -0
  49. package/source/is-union.d.ts +12 -12
  50. package/source/iterable-element.d.ts +5 -5
  51. package/source/jsonify.d.ts +5 -9
  52. package/source/kebab-case.d.ts +1 -0
  53. package/source/kebab-cased-properties-deep.d.ts +7 -0
  54. package/source/kebab-cased-properties.d.ts +5 -1
  55. package/source/keys-of-union.d.ts +2 -2
  56. package/source/last-array-element.d.ts +66 -13
  57. package/source/less-than-or-equal.d.ts +1 -1
  58. package/source/literal-to-primitive.d.ts +1 -1
  59. package/source/literal-union.d.ts +1 -1
  60. package/source/merge-exclusive.d.ts +3 -3
  61. package/source/multidimensional-array.d.ts +1 -1
  62. package/source/multidimensional-readonly-array.d.ts +1 -1
  63. package/source/non-nullable-deep.d.ts +102 -0
  64. package/source/numeric.d.ts +3 -3
  65. package/source/object-merge.d.ts +21 -16
  66. package/source/omit-deep.d.ts +22 -22
  67. package/source/or.d.ts +1 -1
  68. package/source/package-json.d.ts +7 -7
  69. package/source/partial-deep.d.ts +3 -1
  70. package/source/pascal-case.d.ts +1 -0
  71. package/source/pascal-cased-properties-deep.d.ts +7 -0
  72. package/source/pascal-cased-properties.d.ts +5 -1
  73. package/source/pick-deep.d.ts +2 -0
  74. package/source/readonly-deep.d.ts +5 -3
  75. package/source/remove-prefix.d.ts +16 -34
  76. package/source/remove-suffix.d.ts +114 -0
  77. package/source/rename-keys.d.ts +163 -0
  78. package/source/replace.d.ts +2 -2
  79. package/source/require-all-or-none.d.ts +5 -5
  80. package/source/require-at-least-one.d.ts +9 -11
  81. package/source/require-exactly-one.d.ts +7 -7
  82. package/source/require-one-or-none.d.ts +5 -5
  83. package/source/required-deep.d.ts +3 -1
  84. package/source/schema.d.ts +16 -8
  85. package/source/screaming-snake-case.d.ts +1 -0
  86. package/source/set-non-nullable-deep.d.ts +8 -4
  87. package/source/set-non-nullable.d.ts +1 -1
  88. package/source/set-optional.d.ts +5 -5
  89. package/source/set-readonly.d.ts +3 -3
  90. package/source/set-required-deep.d.ts +3 -2
  91. package/source/set-required.d.ts +3 -3
  92. package/source/shared-union-fields-deep.d.ts +4 -3
  93. package/source/shared-union-fields.d.ts +9 -9
  94. package/source/snake-case.d.ts +1 -0
  95. package/source/snake-cased-properties-deep.d.ts +7 -0
  96. package/source/snake-cased-properties.d.ts +5 -1
  97. package/source/some-extend.d.ts +6 -4
  98. package/source/split-on-rest-element.d.ts +6 -4
  99. package/source/split.d.ts +1 -1
  100. package/source/string-length.d.ts +38 -0
  101. package/source/string-repeat.d.ts +48 -21
  102. package/source/string-slice.d.ts +1 -1
  103. package/source/string-to-array.d.ts +97 -0
  104. package/source/string-to-number.d.ts +67 -0
  105. package/source/subtract.d.ts +4 -3
  106. package/source/sum.d.ts +5 -4
  107. package/source/tagged.d.ts +3 -5
  108. package/source/tsconfig-json.d.ts +40 -8
  109. package/source/tuple-of.d.ts +42 -8
  110. package/source/typed-array.d.ts +1 -0
  111. package/source/union-length.d.ts +27 -0
  112. package/source/union-to-intersection.d.ts +1 -1
  113. package/source/union-to-tuple.d.ts +8 -4
  114. package/source/unwrap-required.d.ts +37 -0
  115. package/source/words.d.ts +30 -4
  116. package/source/writable.d.ts +14 -14
  117. package/source/xor.d.ts +1 -1
@@ -8,13 +8,13 @@ import type {TupleOf} from './tuple-of.d.ts';
8
8
  The implementation of `SplitArrayByIndex` for fixed length arrays.
9
9
  */
10
10
  type SplitFixedArrayByIndex<T extends UnknownArray, SplitIndex extends number> =
11
- SplitIndex extends 0
12
- ? [[], T]
13
- : T extends readonly [...TupleOf<SplitIndex>, ...infer V]
14
- ? T extends readonly [...infer U, ...V]
15
- ? [U, V]
16
- : [never, never]
17
- : [never, never];
11
+ SplitIndex extends 0
12
+ ? [[], T]
13
+ : T extends readonly [...TupleOf<SplitIndex>, ...infer V]
14
+ ? T extends readonly [...infer U, ...V]
15
+ ? [U, V]
16
+ : [never, never]
17
+ : [never, never];
18
18
 
19
19
  /**
20
20
  The implementation of `SplitArrayByIndex` for variable length arrays.
@@ -26,23 +26,23 @@ type SplitVariableArrayByIndex<T extends UnknownArray,
26
26
  ? TupleOf<GreaterThanOrEqual<T1, 0> extends true ? T1 : number, VariablePartOfArray<T>[number]>
27
27
  : [],
28
28
  > =
29
- SplitIndex extends 0
30
- ? [[], T]
31
- : GreaterThanOrEqual<StaticPartOfArray<T>['length'], SplitIndex> extends true
32
- ? [
33
- SplitFixedArrayByIndex<StaticPartOfArray<T>, SplitIndex>[0],
34
- [
35
- ...SplitFixedArrayByIndex<StaticPartOfArray<T>, SplitIndex>[1],
36
- ...VariablePartOfArray<T>,
37
- ],
38
- ]
39
- : [
40
- [
41
- ...StaticPartOfArray<T>,
42
- ...(T2 extends UnknownArray ? T2 : []),
43
- ],
44
- VariablePartOfArray<T>,
45
- ];
29
+ SplitIndex extends 0
30
+ ? [[], T]
31
+ : GreaterThanOrEqual<StaticPartOfArray<T>['length'], SplitIndex> extends true
32
+ ? [
33
+ SplitFixedArrayByIndex<StaticPartOfArray<T>, SplitIndex>[0],
34
+ [
35
+ ...SplitFixedArrayByIndex<StaticPartOfArray<T>, SplitIndex>[1],
36
+ ...VariablePartOfArray<T>,
37
+ ],
38
+ ]
39
+ : [
40
+ [
41
+ ...StaticPartOfArray<T>,
42
+ ...(T2 extends UnknownArray ? T2 : []),
43
+ ],
44
+ VariablePartOfArray<T>,
45
+ ];
46
46
 
47
47
  /**
48
48
  Split the given array `T` by the given `SplitIndex`.
@@ -51,13 +51,13 @@ const availableTopSciFi = curry(searchBooks)('sci-fi')(4.5)(true);
51
51
 
52
52
  @category Array
53
53
  */
54
- export type ArrayTail<TArray extends UnknownArray> = IfNotAnyOrNever<TArray,
55
- TArray extends UnknownArray // For distributing `TArray`
54
+ export type ArrayTail<TArray extends UnknownArray> = IfNotAnyOrNever<TArray, {
55
+ ifNot: TArray extends UnknownArray // For distributing `TArray`
56
56
  ? _ArrayTail<TArray> extends infer Result
57
57
  ? If<IsArrayReadonly<TArray>, Readonly<Result>, Result>
58
58
  : never // Should never happen
59
- : never
60
- >;
59
+ : never;
60
+ }>;
61
61
 
62
62
  type _ArrayTail<TArray extends UnknownArray> = TArray extends readonly [unknown?, ...infer Tail]
63
63
  ? keyof TArray & `${number}` extends never
@@ -1,5 +1,5 @@
1
1
  import type {ApplyDefaultOptions} from './internal/index.d.ts';
2
- import type {Words, WordsOptions} from './words.d.ts';
2
+ import type {_DefaultWordsOptions, Words, WordsOptions} from './words.d.ts';
3
3
 
4
4
  /**
5
5
  CamelCase options.
@@ -13,13 +13,39 @@ export type CamelCaseOptions = WordsOptions & {
13
13
  @default false
14
14
  */
15
15
  preserveConsecutiveUppercase?: boolean;
16
+
17
+ /**
18
+ Whether to preserve leading underscores.
19
+
20
+ This matches the behavior of the [`camelcase`](https://github.com/sindresorhus/camelcase) package v9+.
21
+
22
+ @default false
23
+ */
24
+ preserveLeadingUnderscores?: boolean;
16
25
  };
17
26
 
18
- export type _DefaultCamelCaseOptions = {
19
- splitOnNumbers: true;
27
+ export type _DefaultCamelCaseOptions = _DefaultWordsOptions & {
20
28
  preserveConsecutiveUppercase: false;
29
+ preserveLeadingUnderscores: false;
21
30
  };
22
31
 
32
+ /**
33
+ Extract leading underscores from a string.
34
+
35
+ @example
36
+ ```
37
+ type A = LeadingUnderscores<'__foo_bar'>;
38
+ //=> '__'
39
+
40
+ type B = LeadingUnderscores<'foo_bar'>;
41
+ //=> ''
42
+ ```
43
+ */
44
+ type LeadingUnderscores<Type extends string, Underscores extends string = ''> =
45
+ Type extends `_${infer Rest}`
46
+ ? LeadingUnderscores<Rest, `_${Underscores}`>
47
+ : Underscores;
48
+
23
49
  /**
24
50
  Convert an array of words to camel-case.
25
51
  */
@@ -43,6 +69,8 @@ This can be useful when, for example, converting some kebab-cased command-line f
43
69
 
44
70
  By default, consecutive uppercase letter are preserved. See {@link CamelCaseOptions.preserveConsecutiveUppercase preserveConsecutiveUppercase} option to change this behaviour.
45
71
 
72
+ Use the `preserveLeadingUnderscores` option to retain leading underscores, matching the runtime behavior of [`camelcase`](https://github.com/sindresorhus/camelcase) v9+.
73
+
46
74
  @example
47
75
  ```
48
76
  import type {CamelCase} from 'type-fest';
@@ -51,6 +79,8 @@ import type {CamelCase} from 'type-fest';
51
79
 
52
80
  const someVariable: CamelCase<'foo-bar'> = 'fooBar';
53
81
  const preserveConsecutiveUppercase: CamelCase<'foo-BAR-baz', {preserveConsecutiveUppercase: true}> = 'fooBARBaz';
82
+ const splitOnPunctuation: CamelCase<'foo-bar:BAZ', {splitOnPunctuation: true}> = 'fooBarBaz';
83
+ const preserveLeadingUnderscores: CamelCase<'_foo_bar', {preserveLeadingUnderscores: true}> = '_fooBar';
54
84
 
55
85
  // Advanced
56
86
 
@@ -83,10 +113,13 @@ const dbResult: CamelCasedProperties<RawOptions> = {
83
113
  export type CamelCase<Type, Options extends CamelCaseOptions = {}> = Type extends string
84
114
  ? string extends Type
85
115
  ? Type
86
- : Uncapitalize<CamelCaseFromArray<
116
+ : `${Options['preserveLeadingUnderscores'] extends true
117
+ ? LeadingUnderscores<Type>
118
+ : ''
119
+ }${Uncapitalize<CamelCaseFromArray<
87
120
  Words<Type extends Uppercase<Type> ? Lowercase<Type> : Type, Options>,
88
121
  ApplyDefaultOptions<CamelCaseOptions, _DefaultCamelCaseOptions, Options>
89
- >>
122
+ >>}`
90
123
  : Type;
91
124
 
92
125
  export {};
@@ -48,6 +48,13 @@ const preserveConsecutiveUppercase: CamelCasedPropertiesDeep<{fooBAR: {fooBARBiz
48
48
  }],
49
49
  },
50
50
  };
51
+
52
+ const splitOnPunctuation: CamelCasedPropertiesDeep<{'user@info': {'user::id': number; 'user::name': string}}, {splitOnPunctuation: true}> = {
53
+ userInfo: {
54
+ userId: 1,
55
+ userName: 'Tom',
56
+ },
57
+ };
51
58
  ```
52
59
 
53
60
  @category Change case
@@ -86,11 +93,11 @@ type CamelCasedPropertiesArrayDeep<
86
93
  ? [_CamelCasedPropertiesDeep<U, Options>, ..._CamelCasedPropertiesDeep<V, Options>]
87
94
  : Value extends readonly [infer U, ...infer V]
88
95
  ? readonly [_CamelCasedPropertiesDeep<U, Options>, ..._CamelCasedPropertiesDeep<V, Options>]
89
- : // Leading spread array
90
- Value extends readonly [...infer U, infer V]
96
+ // Leading spread array
97
+ : Value extends readonly [...infer U, infer V]
91
98
  ? [..._CamelCasedPropertiesDeep<U, Options>, _CamelCasedPropertiesDeep<V, Options>]
92
- : // Array
93
- Value extends Array<infer U>
99
+ // Array
100
+ : Value extends Array<infer U>
94
101
  ? Array<_CamelCasedPropertiesDeep<U, Options>>
95
102
  : Value extends ReadonlyArray<infer U>
96
103
  ? ReadonlyArray<_CamelCasedPropertiesDeep<U, Options>>
@@ -2,7 +2,7 @@ import type {CamelCase, CamelCaseOptions, _DefaultCamelCaseOptions} from './came
2
2
  import type {ApplyDefaultOptions} from './internal/index.d.ts';
3
3
 
4
4
  /**
5
- Convert object properties to camel case but not recursively.
5
+ Convert top-level object properties to camel case.
6
6
 
7
7
  This can be useful when, for example, converting some API types from a different style.
8
8
 
@@ -26,6 +26,10 @@ const result: CamelCasedProperties<User> = {
26
26
  const preserveConsecutiveUppercase: CamelCasedProperties<{fooBAR: string}, {preserveConsecutiveUppercase: true}> = {
27
27
  fooBAR: 'string',
28
28
  };
29
+
30
+ const splitOnPunctuation: CamelCasedProperties<{'foo::bar': string}, {splitOnPunctuation: true}> = {
31
+ fooBar: 'string',
32
+ };
29
33
  ```
30
34
 
31
35
  @category Change case
@@ -50,7 +50,7 @@ type NumberValueIndices = ConditionalKeys<[string, number?, string?], number | u
50
50
  @category Object
51
51
  */
52
52
  export type ConditionalKeys<Base, Condition> = (Base extends UnknownArray ? TupleToObject<Base> : Base) extends infer _Base // Remove non-numeric keys from arrays
53
- ? IfNotAnyOrNever<_Base, _ConditionalKeys<_Base, Condition>, keyof _Base>
53
+ ? IfNotAnyOrNever<_Base, {ifNot: _ConditionalKeys<_Base, Condition>; ifAny: keyof _Base}>
54
54
  : never;
55
55
 
56
56
  type _ConditionalKeys<Base, Condition> = keyof {
@@ -1,7 +1,6 @@
1
1
  import type {ApplyDefaultOptions, AsciiPunctuation, StartsWith} from './internal/index.d.ts';
2
- import type {IsStringLiteral} from './is-literal.d.ts';
2
+ import type {IsStringLiteral} from './is-string-literal.d.ts';
3
3
  import type {Merge} from './merge.d.ts';
4
- import type {RemovePrefix} from './remove-prefix.d.ts';
5
4
  import type {_DefaultWordsOptions, Words, WordsOptions} from './words.d.ts';
6
5
 
7
6
  export type _DefaultDelimiterCaseOptions = Merge<_DefaultWordsOptions, {splitOnNumbers: false}>;
@@ -17,7 +16,7 @@ type DelimiterCaseFromArray<
17
16
  infer FirstWord extends string,
18
17
  ...infer RemainingWords extends string[],
19
18
  ]
20
- ? DelimiterCaseFromArray<RemainingWords, Delimiter, `${OutputString}${
19
+ ? DelimiterCaseFromArray<RemainingWords, Delimiter, OutputString extends '' ? FirstWord : `${OutputString}${
21
20
  StartsWith<FirstWord, AsciiPunctuation> extends true ? '' : Delimiter
22
21
  }${FirstWord}`>
23
22
  : OutputString;
@@ -38,6 +37,7 @@ import type {DelimiterCase} from 'type-fest';
38
37
 
39
38
  const someVariable: DelimiterCase<'fooBar', '#'> = 'foo#bar';
40
39
  const someVariableNoSplitOnNumbers: DelimiterCase<'p2pNetwork', '#', {splitOnNumbers: false}> = 'p2p#network';
40
+ const someVariableWithPunctuation: DelimiterCase<'div.card::after', '#', {splitOnPunctuation: true}> = 'div#card#after';
41
41
 
42
42
  // Advanced
43
43
 
@@ -66,12 +66,14 @@ export type DelimiterCase<
66
66
  Delimiter extends string,
67
67
  Options extends WordsOptions = {},
68
68
  > = Value extends string
69
- ? IsStringLiteral<Value> extends false
70
- ? Value
71
- : Lowercase<RemovePrefix<DelimiterCaseFromArray<
72
- Words<Value, ApplyDefaultOptions<WordsOptions, _DefaultDelimiterCaseOptions, Options>>,
73
- Delimiter
74
- >, string, {strict: false}>>
69
+ ? Delimiter extends string // For distributing `Delimiter`
70
+ ? IsStringLiteral<Value> extends false
71
+ ? Value
72
+ : Lowercase<DelimiterCaseFromArray<
73
+ Words<Value, ApplyDefaultOptions<WordsOptions, _DefaultDelimiterCaseOptions, Options>>,
74
+ Delimiter
75
+ >>
76
+ : never
75
77
  : Value;
76
78
 
77
79
  export {};
@@ -4,7 +4,7 @@ import type {UnknownArray} from './unknown-array.d.ts';
4
4
  import type {WordsOptions} from './words.d.ts';
5
5
 
6
6
  /**
7
- Convert object properties to delimiter case recursively.
7
+ Convert object properties to a custom string delimiter casing recursively.
8
8
 
9
9
  This can be useful when, for example, converting some API types from a different style.
10
10
 
@@ -51,6 +51,13 @@ const splitOnNumbers: DelimiterCasedPropertiesDeep<{line1: {line2: [{line3: stri
51
51
  ],
52
52
  },
53
53
  };
54
+
55
+ const splitOnPunctuation: DelimiterCasedPropertiesDeep<{'user@info': {'user::id': number; 'user::name': string}}, '-', {splitOnPunctuation: true}> = {
56
+ 'user-info': {
57
+ 'user-id': 1,
58
+ 'user-name': 'Tom',
59
+ },
60
+ };
54
61
  ```
55
62
 
56
63
  @category Change case
@@ -3,7 +3,7 @@ import type {ApplyDefaultOptions} from './internal/index.d.ts';
3
3
  import type {WordsOptions} from './words.d.ts';
4
4
 
5
5
  /**
6
- Convert object properties to delimiter case but not recursively.
6
+ Convert object properties to a custom string delimiter casing.
7
7
 
8
8
  This can be useful when, for example, converting some API types from a different style.
9
9
 
@@ -27,6 +27,10 @@ const result: DelimiterCasedProperties<User, '-'> = {
27
27
  const splitOnNumbers: DelimiterCasedProperties<{line1: string}, '-', {splitOnNumbers: true}> = {
28
28
  'line-1': 'string',
29
29
  };
30
+
31
+ const splitOnPunctuation: DelimiterCasedProperties<{'foo::bar': string}, '-', {splitOnPunctuation: true}> = {
32
+ 'foo-bar': 'string',
33
+ };
30
34
  ```
31
35
 
32
36
  @category Change case
@@ -32,7 +32,7 @@ Unfortunately, `Record<string, never>`, `Record<keyof any, never>` and `Record<n
32
32
  export type EmptyObject = {[emptyObjectSymbol]?: never};
33
33
 
34
34
  /**
35
- Returns a `boolean` for whether the type is strictly equal to an empty plain object, the `{}` value.
35
+ Returns a boolean for whether the type is strictly equal to an empty plain object, the `{}` value.
36
36
 
37
37
  @example
38
38
  ```
@@ -6,7 +6,7 @@ type ObjectEntries<BaseType> = Array<_ObjectEntry<BaseType>>;
6
6
  type SetEntries<BaseType extends Set<unknown>> = Array<_SetEntry<BaseType>>;
7
7
 
8
8
  /**
9
- Many collections have an `entries` method which returns an array of a given object's own enumerable string-keyed property [key, value] pairs. The `Entries` type will return the type of that collection's entries.
9
+ Create a type that describes the key-value pairs produced when calling a collection’s `entries` method.
10
10
 
11
11
  For example the {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries|`Object`}, {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/entries|`Map`}, {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/entries|`Array`}, and {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/entries|`Set`} collections all have this method. Note that `WeakMap` and `WeakSet` do not have this method since their entries are not enumerable.
12
12
 
package/source/entry.d.ts CHANGED
@@ -7,7 +7,7 @@ export type _ObjectEntry<BaseType> = [keyof BaseType, BaseType[keyof BaseType]];
7
7
  export type _SetEntry<BaseType> = BaseType extends Set<infer ItemType> ? [ItemType, ItemType] : never;
8
8
 
9
9
  /**
10
- Many collections have an `entries` method which returns an array of a given object's own enumerable string-keyed property [key, value] pairs. The `Entry` type will return the type of that collection's entry.
10
+ Create a type that describes a single key-value pair produced when calling a collection’s `entries` method.
11
11
 
12
12
  For example the {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries|`Object`}, {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/entries|`Map`}, {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/entries|`Array`}, and {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/entries|`Set`} collections all have this method. Note that `WeakMap` and `WeakSet` do not have this method since their entries are not enumerable.
13
13
 
@@ -33,25 +33,25 @@ type TestExcludeExactly3 = ExcludeExactly<{a: string} | {a: string; b: string},
33
33
  @category Improved Built-in
34
34
  */
35
35
  export type ExcludeExactly<Union, Delete> =
36
- IfNotAnyOrNever<
37
- Union,
38
- _ExcludeExactly<Union, Delete>,
36
+ IfNotAnyOrNever<Union, {
37
+ ifNot: _ExcludeExactly<Union, Delete>;
39
38
  // If `Union` is `any`, then if `Delete` is `any`, return `never`, else return `Union`.
40
- If<IsAny<Delete>, never, Union>,
39
+ ifAny: If<IsAny<Delete>, never, Union>;
41
40
  // If `Union` is `never`, then if `Delete` is `never`, return `never`, else return `Union`.
42
- If<IsNever<Delete>, never, Union>
43
- >;
41
+ ifNever: If<IsNever<Delete>, never, Union>;
42
+ }>;
44
43
 
45
44
  type _ExcludeExactly<Union, Delete> =
46
- IfNotAnyOrNever<Delete,
47
- Union extends unknown // For distributing `Union`
45
+ IfNotAnyOrNever<Delete, {
46
+ ifNot: Union extends unknown // For distributing `Union`
48
47
  ? [Delete extends unknown // For distributing `Delete`
49
48
  ? If<IsEqual<Union, Delete>, true, never>
50
49
  : never] extends [never] ? Union : never
51
- : never,
50
+ : never;
52
51
  // If `Delete` is `any` or `never`, then return `Union`,
53
52
  // because `Union` cannot be `any` or `never` here.
54
- Union, Union
55
- >;
53
+ ifAny: Union;
54
+ ifNever: Union;
55
+ }>;
56
56
 
57
57
  export {};
@@ -27,14 +27,14 @@ type T4 = ExcludeRestElement<[number, string]>;
27
27
  @see {@link SplitOnRestElement}
28
28
  @category Array
29
29
  */
30
- export type ExcludeRestElement<Array_ extends UnknownArray> = IfNotAnyOrNever<Array_,
31
- SplitOnRestElement<Array_> extends infer Result
30
+ export type ExcludeRestElement<Array_ extends UnknownArray> = IfNotAnyOrNever<Array_, {
31
+ ifNot: SplitOnRestElement<Array_> extends infer Result
32
32
  ? Result extends readonly UnknownArray[]
33
33
  ? IsArrayReadonly<Array_> extends true
34
34
  ? Readonly<[...Result[0], ...Result[2]]>
35
35
  : [...Result[0], ...Result[2]]
36
36
  : never
37
- : never
38
- >;
37
+ : never;
38
+ }>;
39
39
 
40
40
  export {};
@@ -125,13 +125,13 @@ type D = ExclusifyUnion<{a?: 1; readonly b: 2} | {d: 4}>;
125
125
  @category Object
126
126
  @category Union
127
127
  */
128
- export type ExclusifyUnion<Union> = IfNotAnyOrNever<Union,
129
- If<IsUnknown<Union>, Union,
128
+ export type ExclusifyUnion<Union> = IfNotAnyOrNever<Union, {
129
+ ifNot: If<IsUnknown<Union>, Union,
130
130
  Extract<Union, NonRecursiveType | MapsSetsOrArrays> extends infer SkippedMembers
131
131
  ? SkippedMembers | _ExclusifyUnion<Exclude<Union, SkippedMembers>>
132
132
  : never
133
- >
134
- >;
133
+ >;
134
+ }>;
135
135
 
136
136
  type _ExclusifyUnion<Union, UnionCopy = Union> = Union extends unknown // For distributing `Union`
137
137
  ? Simplify<
@@ -1,44 +1,151 @@
1
1
  import type {IsNever} from './is-never.d.ts';
2
2
  import type {IsAny} from './is-any.d.ts';
3
+ import type {ApplyDefaultOptions} from './internal/object.d.ts';
4
+ import type {And} from './and.d.ts';
5
+ import type {Or} from './or.d.ts';
6
+ import type {IsUnknown} from './is-unknown.d.ts';
7
+ import type {OrAll} from './or-all.d.ts';
3
8
 
4
- /**
5
- A stricter, non-distributive version of `extends` for checking whether one type is assignable to another.
9
+ export type ExtendsStrictOptions = {
10
+ /**
11
+ Whether to distribute over unions.
12
+
13
+ @default false
14
+
15
+ @example
16
+ ```
17
+ import type {ExtendsStrict} from 'type-fest';
18
+
19
+ type T1 = ExtendsStrict<string | number, string, {distributiveUnions: true}>;
20
+ //=> boolean
21
+
22
+ type T2 = ExtendsStrict<string | number, string, {distributiveUnions: false}>;
23
+ //=> false
24
+ ```
25
+ */
26
+ distributiveUnions?: boolean;
27
+
28
+ /**
29
+ Whether `never` extends every other type.
30
+
31
+ When enabled, `never` is not treated as a bottom type and only extends itself (or `any` / `unknown`).
32
+
33
+ @default true
34
+
35
+ @example
36
+ ```
37
+ import type {ExtendsStrict} from 'type-fest';
38
+
39
+ type T1 = ExtendsStrict<never, number, {strictNever: true}>;
40
+ //=> false
41
+
42
+ type T2 = ExtendsStrict<never, number, {strictNever: false}>;
43
+ //=> true
44
+
45
+ type T3 = ExtendsStrict<never, never, {strictNever: true}>;
46
+ //=> true
47
+
48
+ type T4 = ExtendsStrict<never, any, {strictNever: true}>;
49
+ //=> true
50
+
51
+ type T5 = ExtendsStrict<never, unknown, {strictNever: true}>;
52
+ //=> true
53
+ ```
54
+
55
+ Note: This option only has an effect when checking assignability from `never` (`ExtendsStrict<never, ...>`), and not when checking assignability to `never` (`ExtendsStrict<..., never>`).
56
+ */
57
+ strictNever?: boolean;
58
+
59
+ /**
60
+ Whether `any` extends every other type.
61
+
62
+ When enabled, `any` does not extend every other type, it only extends itself (or `unknown`).
63
+
64
+ @default false
6
65
 
7
- Unlike the built-in `extends` keyword, `ExtendsStrict`:
66
+ @example
67
+ ```
68
+ import type {ExtendsStrict} from 'type-fest';
8
69
 
9
- 1. Prevents distribution over union types by wrapping both types in tuples. For example, `ExtendsStrict<string | number, number>` returns `false`, whereas `string | number extends number` would result in `boolean`.
70
+ type T1 = ExtendsStrict<any, number, {strictAny: true}>;
71
+ //=> false
10
72
 
11
- 2. Treats `never` as a special case: `never` doesn't extend every other type, it only extends itself (or `any`). For example, `ExtendsStrict<never, number>` returns `false` whereas `never extends number` would result in `true`.
73
+ type T2 = ExtendsStrict<any, number, {strictAny: false; distributiveUnions: false}>;
74
+ //=> true
75
+
76
+ type T3 = ExtendsStrict<any, any, {strictAny: true}>;
77
+ //=> true
78
+
79
+ type T4 = ExtendsStrict<any, unknown, {strictAny: true}>;
80
+ //=> true
81
+ ```
82
+
83
+ Note: If `strictAny` is `false` and `distributiveUnions` is `true`, then `any` would distribute and the result would be the `boolean` type, except when checking assignability to `any` or `unknown`.
84
+
85
+ @example
86
+ ```
87
+ import type {ExtendsStrict} from 'type-fest';
88
+
89
+ type T1 = ExtendsStrict<any, number, {strictAny: false; distributiveUnions: true}>;
90
+ //=> boolean
91
+
92
+ type T2 = ExtendsStrict<any, any, {strictAny: false; distributiveUnions: true}>;
93
+ //=> true
94
+
95
+ type T3 = ExtendsStrict<any, unknown, {strictAny: false; distributiveUnions: true}>;
96
+ //=> true
97
+ ```
98
+
99
+ Note: This option only has an effect when checking assignability from `any` (`ExtendsStrict<any, ...>`), and not when checking assignability to `any` (`ExtendsStrict<..., any>`).
100
+ */
101
+ strictAny?: boolean;
102
+ };
103
+
104
+ type DefaultExtendsStrictOptions = {
105
+ distributiveUnions: false;
106
+ strictNever: true;
107
+ strictAny: false;
108
+ };
109
+
110
+ /**
111
+ A customizable version of `extends` for checking whether one type is assignable to another.
112
+
113
+ Refer {@link ExtendsStrictOptions} for the different ways you can customize the behavior of this type.
12
114
 
13
115
  @example
14
116
  ```
15
117
  import type {ExtendsStrict} from 'type-fest';
16
118
 
17
- type T1 = ExtendsStrict<number | string, string>;
119
+ type T1 = ExtendsStrict<number | string, string, {distributiveUnions: false}>;
18
120
  //=> false
19
121
 
20
- type T2 = ExtendsStrict<never, number>;
122
+ type T2 = ExtendsStrict<never, number, {strictNever: true}>;
21
123
  //=> false
22
124
 
23
- type T3 = ExtendsStrict<never, never>;
24
- //=> true
25
-
26
- type T4 = ExtendsStrict<string, number | string>;
27
- //=> true
28
-
29
- type T5 = ExtendsStrict<string, string>;
30
- //=> true
125
+ type T3 = ExtendsStrict<any, number, {strictAny: true}>;
126
+ //=> false
31
127
  ```
32
128
 
129
+ @see {@link ExtendsStrictOptions}
130
+
33
131
  @category Improved Built-in
34
132
  */
35
- export type ExtendsStrict<Left, Right> =
36
- IsAny<Left | Right> extends true
37
- ? true
133
+ export type ExtendsStrict<Left, Right, Options extends ExtendsStrictOptions = {}> =
134
+ _ExtendsStrict<Left, Right, ApplyDefaultOptions<ExtendsStrictOptions, DefaultExtendsStrictOptions, Options>>;
135
+
136
+ type _ExtendsStrict<Left, Right, Options extends Required<ExtendsStrictOptions>> =
137
+ And<IsAny<Left>, Options['strictAny']> extends true
138
+ ? Or<IsAny<Right>, IsUnknown<Right>>
38
139
  : IsNever<Left> extends true
39
- ? IsNever<Right>
40
- : [Left] extends [Right]
41
- ? true
42
- : false;
140
+ ? Options['strictNever'] extends true
141
+ ? OrAll<[IsNever<Right>, IsAny<Right>, IsUnknown<Right>]>
142
+ : true
143
+ : Options['distributiveUnions'] extends true
144
+ ? Left extends Right
145
+ ? true
146
+ : false
147
+ : [Left] extends [Right]
148
+ ? true
149
+ : false;
43
150
 
44
151
  export {};
@@ -0,0 +1,56 @@
1
+ import type {IsAny} from './is-any.d.ts';
2
+ import type {If} from './if.d.ts';
3
+ import type {IsEqual} from './is-equal.d.ts';
4
+ import type {IfNotAnyOrNever} from './internal/type.d.ts';
5
+
6
+ /**
7
+ A stricter version of `Extract<T, U>` that extracts types only when they are exactly identical.
8
+
9
+ @example
10
+ ```
11
+ import type {ExtractExactly} from 'type-fest';
12
+
13
+ type TestExtract1 = Extract<'a' | 'b' | 'c' | 1 | 2 | 3, string>;
14
+ //=> 'a' | 'b' | 'c'
15
+
16
+ type TestExtractExactly1 = ExtractExactly<'a' | 'b' | 'c' | 1 | 2 | 3, string>;
17
+ //=> never
18
+
19
+ type TestExtract2 = Extract<'a' | 'b' | 'c' | 1 | 2 | 3, any>;
20
+ //=> 'a' | 'b' | 'c' | 1 | 2 | 3
21
+
22
+ type TestExtractExactly2 = ExtractExactly<'a' | 'b' | 'c' | 1 | 2 | 3, any>;
23
+ //=> never
24
+
25
+ type TestExtract3 = Extract<{a: string} | {a: string; b: string}, {a: string}>;
26
+ //=> {a: string} | {a: string; b: string}
27
+
28
+ type TestExtractExactly3 = ExtractExactly<{a: string} | {a: string; b: string}, {a: string}>;
29
+ //=> {a: string}
30
+ ```
31
+
32
+ @category Improved Built-in
33
+ */
34
+ export type ExtractExactly<Union, Match> =
35
+ IfNotAnyOrNever<Union, {
36
+ ifNot: _ExtractExactly<Union, Match>;
37
+ // If `Union` is `any`, then if `Match` is `any`, return `any`, else return `never`.
38
+ ifAny: If<IsAny<Match>, Union, never>;
39
+ // If `Union` is `never`, return `never`, doesn't matter what `Match` is.
40
+ ifNever: never;
41
+ }>;
42
+
43
+ type _ExtractExactly<Union, Match> =
44
+ IfNotAnyOrNever<Match, {
45
+ ifNot: Union extends unknown // For distributing `Union`
46
+ ? [Match extends unknown // For distributing `Match`
47
+ ? If<IsEqual<Union, Match>, true, never>
48
+ : never] extends [never] ? never : Union
49
+ : never;
50
+ // If `Match` is `any` or `never`, then return `never`,
51
+ // because `Union` cannot be `any` or `never` here.
52
+ ifAny: never;
53
+ ifNever: never;
54
+ }>;
55
+
56
+ export {};
package/source/get.d.ts CHANGED
@@ -161,7 +161,7 @@ type PropertyOf<BaseType, Key extends string, Options extends Required<GetOption
161
161
 
162
162
  // This works by first splitting the path based on `.` and `[...]` characters into a tuple of string keys. Then it recursively uses the head key to get the next property of the current object, until there are no keys left. Number keys extract the item type from arrays, or are converted to strings to extract types from tuples and dictionaries with number keys.
163
163
  /**
164
- Get a deeply-nested property from an object using a key path, like Lodash's `.get()` function.
164
+ Get a deeply-nested property from an object using a key path, like [Lodash's `.get()`](https://lodash.com/docs#get) function.
165
165
 
166
166
  Use-case: Retrieve a property from deep inside an API response or some other complex object.
167
167