@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
@@ -69,23 +69,23 @@ function displayPetInfoWithAllUnionFields(petInfo: AllUnionFields<Cat | Dog>) {
69
69
  @category Union
70
70
  */
71
71
  export type AllUnionFields<Union> =
72
- Extract<Union, NonRecursiveType | ReadonlyMap<unknown, unknown> | ReadonlySet<unknown> | UnknownArray> extends infer SkippedMembers
73
- ? Exclude<Union, SkippedMembers> extends infer RelevantMembers
74
- ?
75
- | SkippedMembers
76
- | Simplify<
77
- // Include fields that are common in all union members
78
- SharedUnionFields<RelevantMembers> &
79
- // Include readonly fields present in any union member
80
- {
81
- readonly [P in ReadonlyKeysOfUnion<RelevantMembers>]?: ValueOfUnion<RelevantMembers, P & KeysOfUnion<RelevantMembers>>
82
- } &
83
- // Include remaining fields that are neither common nor readonly
84
- {
85
- [P in Exclude<KeysOfUnion<RelevantMembers>, ReadonlyKeysOfUnion<RelevantMembers> | keyof RelevantMembers>]?: ValueOfUnion<RelevantMembers, P>
86
- }
87
- >
88
- : never
89
- : never;
72
+ Extract<Union, NonRecursiveType | ReadonlyMap<unknown, unknown> | ReadonlySet<unknown> | UnknownArray> extends infer SkippedMembers
73
+ ? Exclude<Union, SkippedMembers> extends infer RelevantMembers
74
+ ? // eslint-disable-line @stylistic/operator-linebreak
75
+ | SkippedMembers
76
+ | Simplify<
77
+ // Include fields that are common in all union members
78
+ SharedUnionFields<RelevantMembers>
79
+ // Include readonly fields present in any union member
80
+ & {
81
+ readonly [P in ReadonlyKeysOfUnion<RelevantMembers>]?: ValueOfUnion<RelevantMembers, P & KeysOfUnion<RelevantMembers>>
82
+ }
83
+ // Include remaining fields that are neither common nor readonly
84
+ & {
85
+ [P in Exclude<KeysOfUnion<RelevantMembers>, ReadonlyKeysOfUnion<RelevantMembers> | keyof RelevantMembers>]?: ValueOfUnion<RelevantMembers, P>
86
+ }
87
+ >
88
+ : never
89
+ : never;
90
90
 
91
91
  export {};
@@ -0,0 +1,76 @@
1
+ import type {AllExtend} from './all-extend.d.ts';
2
+
3
+ /**
4
+ Returns a boolean for whether all of the given elements are `true`.
5
+
6
+ Use-cases:
7
+ - Check if all conditions in a list of booleans are met.
8
+
9
+ @example
10
+ ```
11
+ import type {AndAll} from 'type-fest';
12
+
13
+ type TTT = AndAll<[true, true, true]>;
14
+ //=> true
15
+
16
+ type TTF = AndAll<[true, true, false]>;
17
+ //=> false
18
+
19
+ type TFT = AndAll<[true, false, true]>;
20
+ //=> false
21
+ ```
22
+
23
+ Note: When `boolean` is passed as an element, it is distributed into separate cases, and the final result is a union of those cases.
24
+ For example, `AndAll<[true, boolean]>` expands to `AndAll<[true, true]> | AndAll<[true, false]>`, which simplifies to `true | false` (i.e., `boolean`).
25
+
26
+ @example
27
+ ```
28
+ import type {AndAll} from 'type-fest';
29
+
30
+ type A = AndAll<[true, boolean]>;
31
+ //=> boolean
32
+
33
+ type B = AndAll<[false, boolean]>;
34
+ //=> false
35
+ ```
36
+
37
+ Note: If any of the elements is `never`, the result becomes `false`.
38
+
39
+ @example
40
+ ```
41
+ import type {AndAll} from 'type-fest';
42
+
43
+ type A = AndAll<[true, true, never]>;
44
+ //=> false
45
+
46
+ type B = AndAll<[false, never, never]>;
47
+ //=> false
48
+
49
+ type C = AndAll<[never, never, never]>;
50
+ //=> false
51
+
52
+ type D = AndAll<[boolean, true, never]>;
53
+ //=> false
54
+ ```
55
+
56
+ Note: If `any` is passed as an element, it is treated as `boolean` and the result is computed accordingly.
57
+
58
+ @example
59
+ ```
60
+ import type {AndAll} from 'type-fest';
61
+
62
+ type A = AndAll<[false, any]>;
63
+ //=> false
64
+
65
+ type B = AndAll<[true, any]>;
66
+ //=> boolean
67
+ ```
68
+
69
+ Note: `AndAll<[]>` evaluates to `true` due to the concept of [vacuous truth](https://en.wikipedia.org/wiki/Logical_conjunction#:~:text=In%20keeping%20with%20the%20concept%20of%20vacuous%20truth%2C%20when%20conjunction%20is%20defined%20as%20an%20operator%20or%20function%20of%20arbitrary%20arity%2C%20the%20empty%20conjunction%20(AND%2Ding%20over%20an%20empty%20set%20of%20operands)%20is%20often%20defined%20as%20having%20the%20result%20true.), i.e., there are no `false` elements in an empty tuple.
70
+
71
+ @see {@link And}
72
+ @see {@link OrAll}
73
+ */
74
+ export type AndAll<T extends readonly boolean[]> = AllExtend<T, true>;
75
+
76
+ export {};
package/source/and.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import type {AllExtend} from './all-extend.d.ts';
1
+ import type {AndAll} from './and-all.d.ts';
2
2
 
3
3
  /**
4
- Returns a boolean for whether two given types are both true.
4
+ Returns a boolean for whether two given types are both `true`.
5
5
 
6
6
  Use-case: Constructing complex conditional types where multiple conditions must be satisfied.
7
7
 
@@ -73,9 +73,10 @@ type G = And<never, never>;
73
73
  //=> false
74
74
  ```
75
75
 
76
+ @see {@link AndAll}
76
77
  @see {@link Or}
77
78
  @see {@link Xor}
78
79
  */
79
- export type And<A extends boolean, B extends boolean> = AllExtend<[A, B], true>;
80
+ export type And<A extends boolean, B extends boolean> = AndAll<[A, B]>;
80
81
 
81
82
  export {};
@@ -0,0 +1,36 @@
1
+ /**
2
+ Return the length of an array. Equivalent to `T['length']` where `T` extends any array.
3
+
4
+ Tuples resolve to numeric literals, while non-tuples resolve to the `number` type.
5
+
6
+ @example
7
+ ```
8
+ import type {ArrayLength} from 'type-fest';
9
+
10
+ type TupleLength = ArrayLength<[1, 2, 3]>;
11
+ //=> 3
12
+
13
+ type TupleWithOptionalMembersLength = ArrayLength<[1, 2, number?]>;
14
+ //=> 2 | 3
15
+
16
+ type NonTupleArrayLength = ArrayLength<string[]>;
17
+ //=> number
18
+
19
+ type TupleWithRestElementLength = ArrayLength<[1, 2, ...string[]]>;
20
+ //=> number
21
+
22
+ // Distinguish between arrays with fixed and non-fixed lengths
23
+ type IsFixedLengthArray<T extends readonly unknown[]> = number extends ArrayLength<T> ? false : true;
24
+
25
+ type A = IsFixedLengthArray<number[]>;
26
+ //=> false
27
+
28
+ type B = IsFixedLengthArray<[1, 2, 3]>;
29
+ //=> true
30
+ ```
31
+
32
+ @category Array
33
+ */
34
+ export type ArrayLength<T extends readonly unknown[]> = T['length'];
35
+
36
+ export {};
@@ -51,12 +51,13 @@ type E = ArrayReverse<[string?, number?, ...boolean[]]>;
51
51
 
52
52
  @category Array
53
53
  */
54
- export type ArrayReverse<TArray extends UnknownArray> = IfNotAnyOrNever<TArray,
55
- TArray extends unknown // For distributing `TArray`
54
+ export type ArrayReverse<TArray extends UnknownArray> = IfNotAnyOrNever<TArray, {
55
+ ifNot: TArray extends unknown // For distributing `TArray`
56
56
  ? _ArrayReverse<TArray> extends infer Result
57
57
  ? If<IsArrayReadonly<TArray>, Readonly<Result>, Result>
58
58
  : never // Should never happen
59
- : never>; // Should never happen
59
+ : never; // Should never happen
60
+ }>;
60
61
 
61
62
  type _ArrayReverse<
62
63
  TArray extends UnknownArray,
@@ -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`.
@@ -50,10 +50,10 @@ Split the given array `T` by the given `SplitIndex`.
50
50
  @example
51
51
  ```
52
52
  type A = SplitArrayByIndex<[1, 2, 3, 4], 2>;
53
- // type A = [[1, 2], [3, 4]];
53
+ //=> [[1, 2], [3, 4]];
54
54
 
55
55
  type B = SplitArrayByIndex<[1, 2, 3, 4], 0>;
56
- // type B = [[], [1, 2, 3, 4]];
56
+ //=> [[], [1, 2, 3, 4]];
57
57
  ```
58
58
  */
59
59
  type SplitArrayByIndex<T extends UnknownArray, SplitIndex extends number> =
@@ -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 {
@@ -74,7 +74,7 @@ type BooleanPick = ConditionalPickDeep<Example, boolean | undefined>;
74
74
  //=> {c: {e: {g?: boolean}; j: boolean}}
75
75
 
76
76
  type NumberPick = ConditionalPickDeep<Example, number>;
77
- //=> {}
77
+ //=> never
78
78
 
79
79
  type StringOrBooleanPick = ConditionalPickDeep<Example, string | boolean>;
80
80
  //=> {
@@ -99,11 +99,13 @@ export type ConditionalPickDeep<
99
99
  Type,
100
100
  Condition,
101
101
  Options extends ConditionalPickDeepOptions = {},
102
- > = _ConditionalPickDeep<
102
+ > = _NeverIfEmpty<_ConditionalPickDeep<
103
103
  Type,
104
104
  Condition,
105
105
  ApplyDefaultOptions<ConditionalPickDeepOptions, DefaultConditionalPickDeepOptions, Options>
106
- >;
106
+ >>;
107
+
108
+ type _NeverIfEmpty<Type> = Type extends EmptyObject ? never : Type;
107
109
 
108
110
  type _ConditionalPickDeep<
109
111
  Type,
@@ -1,4 +1,5 @@
1
1
  import type {ConditionalKeys} from './conditional-keys.d.ts';
2
+ import type {IsNever} from './is-never.d.ts';
2
3
 
3
4
  /**
4
5
  Pick keys from the shape that matches the given `Condition`.
@@ -38,9 +39,10 @@ type StringKeysOnly = ConditionalPick<Example, string>;
38
39
 
39
40
  @category Object
40
41
  */
41
- export type ConditionalPick<Base, Condition> = Pick<
42
- Base,
43
- ConditionalKeys<Base, Condition>
44
- >;
42
+ export type ConditionalPick<Base, Condition> = ConditionalKeys<Base, Condition> extends infer Keys
43
+ ? IsNever<Keys> extends true
44
+ ? never
45
+ : Pick<Base, Keys & keyof Base>
46
+ : never;
45
47
 
46
48
  export {};
@@ -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
 
@@ -0,0 +1,57 @@
1
+ import type {IsNever} from './is-never.d.ts';
2
+ import type {IsAny} from './is-any.d.ts';
3
+ import type {If} from './if.d.ts';
4
+ import type {IsEqual} from './is-equal.d.ts';
5
+ import type {IfNotAnyOrNever} from './internal/type.d.ts';
6
+
7
+ /**
8
+ A stricter version of `Exclude<T, U>` that excludes types only when they are exactly identical.
9
+
10
+ @example
11
+ ```
12
+ import type {ExcludeExactly} from 'type-fest';
13
+
14
+ type TestExclude1 = Exclude<'a' | 'b' | 'c' | 1 | 2 | 3, string>;
15
+ //=> 1 | 2 | 3
16
+
17
+ type TestExcludeExactly1 = ExcludeExactly<'a' | 'b' | 'c' | 1 | 2 | 3, string>;
18
+ //=> 'a' | 'b' | 'c' | 1 | 2 | 3
19
+
20
+ type TestExclude2 = Exclude<'a' | 'b' | 'c' | 1 | 2 | 3, any>;
21
+ //=> never
22
+
23
+ type TestExcludeExactly2 = ExcludeExactly<'a' | 'b' | 'c' | 1 | 2 | 3, any>;
24
+ //=> 'a' | 'b' | 'c' | 1 | 2 | 3
25
+
26
+ type TestExclude3 = Exclude<{a: string} | {a: string; b: string}, {a: string}>;
27
+ //=> never
28
+
29
+ type TestExcludeExactly3 = ExcludeExactly<{a: string} | {a: string; b: string}, {a: string}>;
30
+ //=> {a: string; b: string}
31
+ ```
32
+
33
+ @category Improved Built-in
34
+ */
35
+ export type ExcludeExactly<Union, Delete> =
36
+ IfNotAnyOrNever<Union, {
37
+ ifNot: _ExcludeExactly<Union, Delete>;
38
+ // If `Union` is `any`, then if `Delete` is `any`, return `never`, else return `Union`.
39
+ ifAny: If<IsAny<Delete>, never, Union>;
40
+ // If `Union` is `never`, then if `Delete` is `never`, return `never`, else return `Union`.
41
+ ifNever: If<IsNever<Delete>, never, Union>;
42
+ }>;
43
+
44
+ type _ExcludeExactly<Union, Delete> =
45
+ IfNotAnyOrNever<Delete, {
46
+ ifNot: Union extends unknown // For distributing `Union`
47
+ ? [Delete extends unknown // For distributing `Delete`
48
+ ? If<IsEqual<Union, Delete>, true, never>
49
+ : never] extends [never] ? Union : never
50
+ : never;
51
+ // If `Delete` is `any` or `never`, then return `Union`,
52
+ // because `Union` cannot be `any` or `never` here.
53
+ ifAny: Union;
54
+ ifNever: Union;
55
+ }>;
56
+
57
+ export {};