@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
@@ -0,0 +1,114 @@
1
+ import type {ApplyDefaultOptions} from './internal/object.d.ts';
2
+ import type {IfNotAnyOrNever, Not} from './internal/type.d.ts';
3
+ import type {IsStringLiteral} from './is-string-literal.d.ts';
4
+ import type {IsNever} from './is-never.d.ts';
5
+ import type {Or} from './or.d.ts';
6
+ import type {If} from './if.d.ts';
7
+
8
+ /**
9
+ @see {@link RemoveSuffix}
10
+ */
11
+ export type RemoveSuffixOptions = {
12
+ /**
13
+ When enabled, instantiations with non-literal suffixes (e.g., `string`, `Uppercase<string>`, `` `.${string}` ``) simply return `string`, since their precise structure cannot be statically determined.
14
+
15
+ Note: Disabling this option can produce misleading results that might not reflect the actual runtime behavior.
16
+ For example, ``RemoveSuffix<'report.pdf', `.${string}`, {strict: false}>`` returns `'report'`, but at runtime, suffix could be `'.txt'` (which satisfies `` `.${string}` ``) and removing `'.txt'` from `'report.pdf'` would not result in `'report'`.
17
+
18
+ So, it is recommended to not disable this option unless you are aware of the implications.
19
+
20
+ @default true
21
+
22
+ @example
23
+ ```
24
+ import type {RemoveSuffix} from 'type-fest';
25
+
26
+ type A = RemoveSuffix<'report.pdf', `.${string}`, {strict: true}>;
27
+ //=> string
28
+
29
+ type B = RemoveSuffix<'report.pdf', `.${string}`, {strict: false}>;
30
+ //=> 'report'
31
+
32
+ type C = RemoveSuffix<'on-change', string, {strict: true}>;
33
+ //=> string
34
+
35
+ type D = RemoveSuffix<'on-change', string, {strict: false}>;
36
+ //=> 'o'
37
+
38
+ type E = RemoveSuffix<`${number}/${string}`, `/${string}`, {strict: true}>;
39
+ //=> string
40
+
41
+ type F = RemoveSuffix<`${number}/${string}`, `/${string}`, {strict: false}>;
42
+ //=> `${number}`
43
+ ```
44
+
45
+ Note: This option has no effect when only the input string type is non-literal. For example, ``RemoveSuffix<`${string}.pdf`, '.pdf'>`` will always return `string`.
46
+
47
+ @example
48
+ ```
49
+ import type {RemoveSuffix} from 'type-fest';
50
+
51
+ type A = RemoveSuffix<`${string}.pdf`, '.pdf', {strict: true}>;
52
+ //=> string
53
+
54
+ type B = RemoveSuffix<`${string}.pdf`, '.pdf', {strict: false}>;
55
+ //=> string
56
+
57
+ type C = RemoveSuffix<`${number}px`, 'px', {strict: true}>;
58
+ //=> `${number}`
59
+
60
+ type D = RemoveSuffix<`${number}px`, 'px', {strict: false}>;
61
+ //=> `${number}`
62
+ ```
63
+ */
64
+ strict?: boolean;
65
+ };
66
+
67
+ type DefaultRemoveSuffixOptions = {
68
+ strict: true;
69
+ };
70
+
71
+ /**
72
+ Remove the specified suffix from the end of a string.
73
+
74
+ @example
75
+ ```
76
+ import type {RemoveSuffix} from 'type-fest';
77
+
78
+ type A = RemoveSuffix<'report.pdf', '.pdf'>;
79
+ //=> 'report'
80
+
81
+ type B = RemoveSuffix<'bg-blue-500' | 'text-green-500' | 'border-slate-500', '-500'>;
82
+ //=> 'bg-blue' | 'border-slate' | 'text-green'
83
+
84
+ type C = RemoveSuffix<'report.pdf', '.txt'>;
85
+ //=> 'report.pdf'
86
+
87
+ type D = RemoveSuffix<`api/${string}/analytics`, '/analytics'>;
88
+ //=> `api/${string}`
89
+ ```
90
+
91
+ @see {@link RemoveSuffixOptions}
92
+
93
+ @category String
94
+ @category Template literal
95
+ */
96
+ export type RemoveSuffix<S extends string, Suffix extends string, Options extends RemoveSuffixOptions = {}> =
97
+ IfNotAnyOrNever<S, {
98
+ ifNot: If<
99
+ IsNever<Suffix>,
100
+ S,
101
+ _RemoveSuffix<S, Suffix, ApplyDefaultOptions<RemoveSuffixOptions, DefaultRemoveSuffixOptions, Options>>
102
+ >;
103
+ }>;
104
+
105
+ type _RemoveSuffix<S extends string, Suffix extends string, Options extends Required<RemoveSuffixOptions>> =
106
+ Suffix extends string // For distributing `Suffix`
107
+ ? Or<IsStringLiteral<Suffix>, Not<Options['strict']>> extends true
108
+ ? S extends `${infer Rest}${Suffix}`
109
+ ? Rest
110
+ : S // Return back `S` when `Suffix` is not present at the end of `S`
111
+ : string // Fallback to `string` when `Suffix` is non-literal and `strict` is enabled
112
+ : never;
113
+
114
+ export {};
@@ -0,0 +1,163 @@
1
+ import type {IsLiteral} from './is-literal.d.ts';
2
+ import type {ReadonlyKeysOf} from './readonly-keys-of.d.ts';
3
+ import type {RequiredKeysOf} from './required-keys-of.d.ts';
4
+ import type {OptionalKeysOf} from './optional-keys-of.d.ts';
5
+ import type {OmitIndexSignature} from './omit-index-signature.d.ts';
6
+ import type {SetRequired} from './set-required.d.ts';
7
+ import type {SetReadonly} from './set-readonly.d.ts';
8
+ import type {IfNotAnyOrNever, IsExactOptionalPropertyTypesEnabled} from './internal/type.d.ts';
9
+
10
+ /**
11
+ Rename keys in an object type according to a map of old-to-new names.
12
+
13
+ @example
14
+ ```
15
+ import type {RenameKeys} from 'type-fest';
16
+
17
+ type User = {
18
+ id: string;
19
+ firstName: string;
20
+ createdAt: Date;
21
+ };
22
+
23
+ type Renamed = RenameKeys<User, {firstName: 'first_name'; createdAt: 'created_at'}>;
24
+ //=> {id: string; first_name: string; created_at: Date}
25
+ ```
26
+
27
+ @example
28
+ ```
29
+ import type {RenameKeys} from 'type-fest';
30
+
31
+ type SearchInput = {
32
+ textQuery: string;
33
+ voiceQuery: Blob;
34
+ imageQuery: File;
35
+ };
36
+
37
+ type Normalized = RenameKeys<SearchInput, {textQuery: 'query'; voiceQuery: 'query'; imageQuery: 'query'}>;
38
+ //=> {query: string | Blob | File}
39
+ ```
40
+
41
+ Note: When multiple source keys map to the same target, the target's value type is the union of the contributors' value types. The target is optional only when every contributor is optional, and is `readonly` when any contributor is `readonly`. With `exactOptionalPropertyTypes` disabled, the value type of a mixed-optionality merge also includes `undefined`.
42
+
43
+ @example
44
+ ```
45
+ import type {RenameKeys} from 'type-fest';
46
+
47
+ // All colliding keys are required, so the target is required.
48
+ type A = RenameKeys<{a: 1; b: 2}, {a: 'x'; b: 'x'}>;
49
+ //=> {x: 1 | 2}
50
+
51
+ // All colliding keys are optional, so the target is optional.
52
+ type B = RenameKeys<{a?: 1; b?: 2}, {a: 'x'; b: 'x'}>;
53
+ //=> {x?: 1 | 2}
54
+
55
+ // One of the colliding keys is required, so the target is required.
56
+ type C = RenameKeys<{a: 1; b?: 2}, {a: 'x'; b: 'x'}>;
57
+ //=> {x: 1 | 2}
58
+
59
+ // One of the colliding keys is `readonly`, so the target is `readonly`.
60
+ type D = RenameKeys<{readonly a: 1; b: 2}, {a: 'x'; b: 'x'}>;
61
+ //=> {readonly x: 1 | 2}
62
+ ```
63
+
64
+ @example
65
+ ```
66
+ // @exactOptionalPropertyTypes: false
67
+ import type {RenameKeys} from 'type-fest';
68
+
69
+ // With `exactOptionalPropertyTypes` disabled, a mixed-optionality merge includes `undefined`.
70
+ type E = RenameKeys<{a?: 1; b: 2}, {a: 'x'; b: 'x'}>;
71
+ //=> {x: 1 | 2 | undefined}
72
+ ```
73
+
74
+ Note: A union target distributes, producing one output key per member.
75
+
76
+ @example
77
+ ```
78
+ import type {RenameKeys} from 'type-fest';
79
+
80
+ type A = RenameKeys<{a: string}, {a: 'b' | 'c'}>;
81
+ //=> {b: string; c: string}
82
+ ```
83
+
84
+ Note: An entry whose value is not a literal `PropertyKey` (such as `string`) is also ignored, leaving that key's name unchanged.
85
+
86
+ @example
87
+ ```
88
+ import type {RenameKeys} from 'type-fest';
89
+
90
+ type A = RenameKeys<{a: 1}, {a: string}>;
91
+ //=> {a: 1}
92
+
93
+ type B = RenameKeys<{a: 1; b: 2}, {a: 'x'; b: symbol}>;
94
+ //=> {x: 1; b: 2}
95
+ ```
96
+
97
+ Note: A rename map entry whose key is not a property of the source type is ignored.
98
+
99
+ @example
100
+ ```
101
+ import type {RenameKeys} from 'type-fest';
102
+
103
+ type A = RenameKeys<{a: 1; b: 2}, {a: 'x'; c: 'y'}>;
104
+ //=> {x: 1; b: 2}
105
+ ```
106
+
107
+ @category Object
108
+ */
109
+ export type RenameKeys<
110
+ BaseType extends object,
111
+ RenameMap extends Record<PropertyKey, PropertyKey>,
112
+ > = IfNotAnyOrNever<BaseType, {
113
+ ifNot: BaseType extends unknown // For distributing `BaseType`
114
+ ? RenameMap extends unknown // For distributing `RenameMap`
115
+ ? RenameOnce<BaseType, NormalizeMap<RenameMap>>
116
+ : never
117
+ : never;
118
+ }>;
119
+
120
+ type RenameOnce<BaseType extends object, RenameMap extends Record<PropertyKey, PropertyKey>> =
121
+ RestoreMergedUndefined<BaseType, RenameMap,
122
+ ApplyReadonly<BaseType, RenameMap,
123
+ ApplyRequired<BaseType, RenameMap,
124
+ RenameNaive<BaseType, RenameMap>>>>;
125
+
126
+ type RenameNaive<BaseType extends object, RenameMap extends Record<PropertyKey, PropertyKey>> = {
127
+ // Two keys mapping to one target produce a union value and keep only the first key's modifiers.
128
+ // Like for example, `{a?: 1; b: 2}` with `{a: 'x'; b: 'x'}` produces `{x?: 1 | 2}`, taking `a`'s optional.
129
+ [Key in keyof BaseType as TargetOf<Key, RenameMap>]: Required<BaseType>[Key];
130
+ };
131
+
132
+ // A merged target kept only one modifier in `RenameNaive`, so re-force these from every contributor.
133
+ type ApplyRequired<BaseType extends object, RenameMap extends Record<PropertyKey, PropertyKey>, Renamed> =
134
+ SetRequired<Renamed, TargetOf<RequiredKeysOf<OmitIndexSignature<BaseType>>, RenameMap> & keyof Renamed>;
135
+
136
+ type ApplyReadonly<BaseType extends object, RenameMap extends Record<PropertyKey, PropertyKey>, Renamed> =
137
+ SetReadonly<Renamed, TargetOf<ReadonlyKeysOf<OmitIndexSignature<BaseType>>, RenameMap> & keyof Renamed>;
138
+
139
+ // `exactOptionalPropertyTypes` off keeps `undefined` on a target that merged a required and an optional source.
140
+ // Source `{a?: 1; x: 2}` with `{a: 'x'}` gives `{x: 1 | 2 | undefined}`.
141
+ type RestoreMergedUndefined<BaseType extends object, RenameMap extends Record<PropertyKey, PropertyKey>, Result> =
142
+ IsExactOptionalPropertyTypesEnabled extends true
143
+ ? Result
144
+ : {
145
+ [Key in keyof Result]: Key extends MergedTargets<BaseType, RenameMap>
146
+ ? Result[Key] | undefined
147
+ : Result[Key];
148
+ };
149
+
150
+ type MergedTargets<BaseType extends object, RenameMap extends Record<PropertyKey, PropertyKey>> =
151
+ // Targets renamed from both a required and an optional key prefer the required modifier.
152
+ // Required `b` and optional `a` both rename to `x` in `{a?: 1; b: 2}` with `{a: 'x'; b: 'x'}`.
153
+ TargetOf<RequiredKeysOf<OmitIndexSignature<BaseType>>, RenameMap>
154
+ & TargetOf<OptionalKeysOf<OmitIndexSignature<BaseType>>, RenameMap>;
155
+
156
+ type NormalizeMap<RenameMap extends Record<PropertyKey, PropertyKey>> = {
157
+ -readonly [Key in keyof RenameMap as true extends IsLiteral<RenameMap[Key]> ? Key : never]-?: RenameMap[Key];
158
+ };
159
+
160
+ type TargetOf<SourceKey extends PropertyKey, RenameMap extends Record<PropertyKey, PropertyKey>> =
161
+ SourceKey extends keyof RenameMap ? RenameMap[SourceKey] : SourceKey;
162
+
163
+ export {};
@@ -27,7 +27,7 @@ declare function replace<
27
27
  >(
28
28
  input: Input,
29
29
  search: Search,
30
- replacement: Replacement
30
+ replacement: Replacement,
31
31
  ): Replace<Input, Search, Replacement>;
32
32
 
33
33
  declare function replaceAll<
@@ -37,7 +37,7 @@ declare function replaceAll<
37
37
  >(
38
38
  input: Input,
39
39
  search: Search,
40
- replacement: Replacement
40
+ replacement: Replacement,
41
41
  ): Replace<Input, Search, Replacement, {all: true}>;
42
42
 
43
43
  // The return type is the exact string literal, not just `string`.
@@ -9,7 +9,7 @@ Requires all of the keys in the given object.
9
9
  type RequireAll<ObjectType, KeysType extends keyof ObjectType> = Required<Pick<ObjectType, KeysType>>;
10
10
 
11
11
  /**
12
- Create a type that requires all of the given keys or none of the given keys. The remaining keys are kept as is.
12
+ Create a type that requires all of the given keys or none of the given keys, while keeping the remaining keys as is.
13
13
 
14
14
  Use-cases:
15
15
  - Creating interfaces for components with mutually-inclusive keys.
@@ -40,11 +40,11 @@ const responder2: RequireAllOrNone<Responder, 'text' | 'json'> = {
40
40
  @category Object
41
41
  */
42
42
  export type RequireAllOrNone<ObjectType, KeysType extends keyof ObjectType = keyof ObjectType> =
43
- IfNotAnyOrNever<ObjectType,
44
- If<IsNever<KeysType>,
43
+ IfNotAnyOrNever<ObjectType, {
44
+ ifNot: If<IsNever<KeysType>,
45
45
  ObjectType,
46
- _RequireAllOrNone<ObjectType, If<IsAny<KeysType>, keyof ObjectType, KeysType>>
47
- >>;
46
+ _RequireAllOrNone<ObjectType, If<IsAny<KeysType>, keyof ObjectType, KeysType>>>;
47
+ }>;
48
48
 
49
49
  type _RequireAllOrNone<ObjectType, KeysType extends keyof ObjectType> = (
50
50
  | RequireAll<ObjectType, KeysType>
@@ -5,7 +5,7 @@ import type {IsAny} from './is-any.d.ts';
5
5
  import type {IsNever} from './is-never.d.ts';
6
6
 
7
7
  /**
8
- Create a type that requires at least one of the given keys. The remaining keys are kept as is.
8
+ Create a type that requires at least one of the given keys, while keeping the remaining keys as is.
9
9
 
10
10
  @example
11
11
  ```
@@ -29,22 +29,20 @@ export type RequireAtLeastOne<
29
29
  ObjectType,
30
30
  KeysType extends keyof ObjectType = keyof ObjectType,
31
31
  > =
32
- IfNotAnyOrNever<ObjectType,
33
- If<IsNever<KeysType>,
32
+ IfNotAnyOrNever<ObjectType, {
33
+ ifNot: If<IsNever<KeysType>,
34
34
  never,
35
- _RequireAtLeastOne<ObjectType, If<IsAny<KeysType>, keyof ObjectType, KeysType>>
36
- >>;
35
+ _RequireAtLeastOne<ObjectType, If<IsAny<KeysType>, keyof ObjectType, KeysType>>>;
36
+ }>;
37
37
 
38
38
  type _RequireAtLeastOne<
39
39
  ObjectType,
40
40
  KeysType extends keyof ObjectType,
41
41
  > = {
42
42
  // For each `Key` in `KeysType` make a mapped type:
43
- [Key in KeysType]-?: Required<Pick<ObjectType, Key>> & // 1. Make `Key`'s type required
44
- // 2. Make all other keys in `KeysType` optional
45
- Partial<Pick<ObjectType, Exclude<KeysType, Key>>>;
46
- }[KeysType] &
47
- // 3. Add the remaining keys not in `KeysType`
48
- Except<ObjectType, KeysType>;
43
+ [Key in KeysType]-?: Required<Pick<ObjectType, Key>> // 1. Make `Key`'s type required
44
+ & Partial<Pick<ObjectType, Exclude<KeysType, Key>>>; // 2. Make all other keys in `KeysType` optional
45
+ }[KeysType]
46
+ & Except<ObjectType, KeysType>; // 3. Add the remaining keys not in `KeysType`
49
47
 
50
48
  export {};
@@ -4,7 +4,7 @@ import type {IsAny} from './is-any.d.ts';
4
4
  import type {IsNever} from './is-never.d.ts';
5
5
 
6
6
  /**
7
- Create a type that requires exactly one of the given keys and disallows more. The remaining keys are kept as is.
7
+ Create a type that requires exactly one of the given keys and disallows more, while keeping the remaining keys as is.
8
8
 
9
9
  Use-cases:
10
10
  - Creating interfaces for components that only need one of the keys to display properly.
@@ -33,16 +33,16 @@ const responder: RequireExactlyOne<Responder, 'text' | 'json'> = {
33
33
  @category Object
34
34
  */
35
35
  export type RequireExactlyOne<ObjectType, KeysType extends keyof ObjectType = keyof ObjectType> =
36
- IfNotAnyOrNever<ObjectType,
37
- If<IsNever<KeysType>,
36
+ IfNotAnyOrNever<ObjectType, {
37
+ ifNot: If<IsNever<KeysType>,
38
38
  never,
39
- _RequireExactlyOne<ObjectType, If<IsAny<KeysType>, keyof ObjectType, KeysType>>
40
- >>;
39
+ _RequireExactlyOne<ObjectType, If<IsAny<KeysType>, keyof ObjectType, KeysType>>>;
40
+ }>;
41
41
 
42
42
  type _RequireExactlyOne<ObjectType, KeysType extends keyof ObjectType> =
43
43
  {[Key in KeysType]: (
44
- Required<Pick<ObjectType, Key>> &
45
- Partial<Record<Exclude<KeysType, Key>, never>>
44
+ Required<Pick<ObjectType, Key>>
45
+ & Partial<Record<Exclude<KeysType, Key>, never>>
46
46
  )}[KeysType] & Omit<ObjectType, KeysType>;
47
47
 
48
48
  export {};
@@ -5,7 +5,7 @@ import type {IsAny} from './is-any.d.ts';
5
5
  import type {IsNever} from './is-never.d.ts';
6
6
 
7
7
  /**
8
- Create a type that requires exactly one of the given keys and disallows more, or none of the given keys. The remaining keys are kept as is.
8
+ Create a type that requires exactly one of the given keys or none of the given keys, while keeping the remaining keys as is.
9
9
 
10
10
  @example
11
11
  ```
@@ -35,11 +35,11 @@ const responder3: Responder = {
35
35
  @category Object
36
36
  */
37
37
  export type RequireOneOrNone<ObjectType, KeysType extends keyof ObjectType = keyof ObjectType> =
38
- IfNotAnyOrNever<ObjectType,
39
- If<IsNever<KeysType>,
38
+ IfNotAnyOrNever<ObjectType, {
39
+ ifNot: If<IsNever<KeysType>,
40
40
  ObjectType,
41
- _RequireOneOrNone<ObjectType, If<IsAny<KeysType>, keyof ObjectType, KeysType>>
42
- >>;
41
+ _RequireOneOrNone<ObjectType, If<IsAny<KeysType>, keyof ObjectType, KeysType>>>;
42
+ }>;
43
43
 
44
44
  type _RequireOneOrNone<ObjectType, KeysType extends keyof ObjectType> = (
45
45
  | RequireExactlyOne<ObjectType, KeysType>
@@ -3,12 +3,14 @@ import type {IsNever} from './is-never.d.ts';
3
3
  import type {Simplify} from './simplify.d.ts';
4
4
 
5
5
  /**
6
- Create a type from another type with all keys and nested keys set to required.
6
+ Create a deeply required version of another type.
7
7
 
8
8
  Use-cases:
9
9
  - Creating optional configuration interfaces where the underlying implementation still requires all options to be fully specified.
10
10
  - Modeling the resulting type after a deep merge with a set of defaults.
11
11
 
12
+ Use [`Required<T>`](https://www.typescriptlang.org/docs/handbook/utility-types.html#requiredtype) if you only need one level deep.
13
+
12
14
  @example
13
15
  ```
14
16
  import type {RequiredDeep} from 'type-fest';
@@ -1,5 +1,7 @@
1
1
  import type {ApplyDefaultOptions} from './internal/object.d.ts';
2
2
  import type {IfNotAnyOrNever, NonRecursiveType} from './internal/type.d.ts';
3
+ import type {IsAny} from './is-any.d.ts';
4
+ import type {IsUnknown} from './is-unknown.d.ts';
3
5
  import type {OptionalKeysOf} from './optional-keys-of.d.ts';
4
6
  import type {Simplify} from './simplify.d.ts';
5
7
  import type {UnknownArray} from './unknown-array.d.ts';
@@ -91,18 +93,24 @@ const userMaskSettings: UserMask = {
91
93
  @category Object
92
94
  */
93
95
  export type Schema<Type, Value, Options extends SchemaOptions = {}> =
94
- IfNotAnyOrNever<Type,
95
- _Schema<Type, Value, ApplyDefaultOptions<SchemaOptions, DefaultSchemaOptions, Options>>,
96
- Value, Value>;
96
+ IfNotAnyOrNever<Type, {
97
+ ifNot: _Schema<Type, Value, ApplyDefaultOptions<SchemaOptions, DefaultSchemaOptions, Options>>;
98
+ ifAny: Value;
99
+ ifNever: Value;
100
+ }>;
97
101
 
98
102
  type _Schema<Type, Value, Options extends Required<SchemaOptions>> =
99
- Type extends NonRecursiveType | Map<unknown, unknown> | Set<unknown> | ReadonlyMap<unknown, unknown> | ReadonlySet<unknown>
103
+ IsAny<Type> extends true
100
104
  ? Value
101
- : Type extends UnknownArray
102
- ? Options['recurseIntoArrays'] extends false
105
+ : IsUnknown<Type> extends true
106
+ ? Value
107
+ : Type extends NonRecursiveType | Map<unknown, unknown> | Set<unknown> | ReadonlyMap<unknown, unknown> | ReadonlySet<unknown>
103
108
  ? Value
104
- : SchemaHelper<Type, Value, Options>
105
- : SchemaHelper<Type, Value, Options>;
109
+ : Type extends UnknownArray
110
+ ? Options['recurseIntoArrays'] extends false
111
+ ? Value
112
+ : SchemaHelper<Type, Value, Options>
113
+ : SchemaHelper<Type, Value, Options>;
106
114
 
107
115
  /**
108
116
  Internal helper for {@link _Schema}.
@@ -14,6 +14,7 @@ import type {ScreamingSnakeCase} from 'type-fest';
14
14
 
15
15
  const someVariable: ScreamingSnakeCase<'fooBar'> = 'FOO_BAR';
16
16
  const someVariableNoSplitOnNumbers: ScreamingSnakeCase<'p2pNetwork', {splitOnNumbers: false}> = 'P2P_NETWORK';
17
+ const someVariableWithPunctuation: ScreamingSnakeCase<'div.card::after', {splitOnPunctuation: true}> = 'DIV_CARD_AFTER';
17
18
 
18
19
  ```
19
20
 
@@ -1,14 +1,17 @@
1
- import type {NonRecursiveType, StringToNumber} from './internal/index.d.ts';
1
+ import type {NonRecursiveType} from './internal/index.d.ts';
2
+ import type {IsAny} from './is-any.d.ts';
3
+ import type {NonNullableDeep} from './non-nullable-deep.d.ts';
2
4
  import type {Paths} from './paths.d.ts';
3
5
  import type {SetNonNullable} from './set-non-nullable.d.ts';
4
6
  import type {Simplify} from './simplify.d.ts';
7
+ import type {StringToNumber} from './string-to-number.d.ts';
5
8
  import type {UnionToTuple} from './union-to-tuple.d.ts';
6
9
  import type {UnknownArray} from './unknown-array.d.ts';
7
10
 
8
11
  /**
9
12
  Create a type that makes the specified keys non-nullable (removes `null` and `undefined`), supports deeply nested key paths, and leaves all other keys unchanged.
10
13
 
11
- NOTE: Optional modifiers (`?`) are not removed from properties. For example, `SetNonNullableDeep<{foo?: string | null | undefined}, 'foo'>` will result in `{foo?: string}`.
14
+ NOTE: Optional modifiers (`?`) are not removed from properties. For example, `SetNonNullableDeep<{foo?: string | null | undefined}, 'foo'>` will result in `{foo?: string}`. To remove both optional modifiers and nullables, use {@link SetRequiredDeep} in conjunction with this type.
12
15
 
13
16
  @example
14
17
  ```
@@ -55,8 +58,9 @@ type ArrayExample2 = SetNonNullableDeep<{a: [(number | null)?, (number | null)?]
55
58
 
56
59
  @category Object
57
60
  */
58
- export type SetNonNullableDeep<BaseType, KeyPaths extends Paths<BaseType>> =
59
- SetNonNullableDeepHelper<BaseType, UnionToTuple<KeyPaths>>;
61
+ export type SetNonNullableDeep<BaseType, KeyPaths extends Paths<BaseType>> = IsAny<KeyPaths> extends true
62
+ ? NonNullableDeep<BaseType>
63
+ : SetNonNullableDeepHelper<BaseType, UnionToTuple<KeyPaths>>;
60
64
 
61
65
  /**
62
66
  Internal helper for {@link SetNonNullableDeep}.
@@ -1,5 +1,5 @@
1
1
  /**
2
- Create a type that makes the given keys non-nullable, where the remaining keys are kept as is.
2
+ Create a type that makes the given keys non-nullable, while keeping the remaining keys as is.
3
3
 
4
4
  If no keys are given, all keys will be made non-nullable.
5
5
 
@@ -15,19 +15,12 @@ type Foo = {
15
15
  c?: boolean | null;
16
16
  };
17
17
 
18
+ // Note: In the following example, `c` can no longer be `null`, but it's still optional.
18
19
  type SomeNonNullable = SetNonNullable<Foo, 'b' | 'c'>;
19
- // type SomeNonNullable = {
20
- // a: number | null;
21
- // b: string; // Can no longer be undefined.
22
- // c?: boolean; // Can no longer be null, but is still optional.
23
- // }
20
+ //=> {a: null | number; b: string; c?: boolean}
24
21
 
25
22
  type AllNonNullable = SetNonNullable<Foo>;
26
- // type AllNonNullable = {
27
- // a: number; // Can no longer be null.
28
- // b: string; // Can no longer be undefined.
29
- // c?: boolean; // Can no longer be null, but is still optional.
30
- // }
23
+ //=> {a: number; b: string; c?: boolean}
31
24
  ```
32
25
 
33
26
  @category Object
@@ -3,7 +3,7 @@ import type {HomomorphicPick} from './internal/index.d.ts';
3
3
  import type {Simplify} from './simplify.d.ts';
4
4
 
5
5
  /**
6
- Create a type that makes the given keys optional. The remaining keys are kept as is. The sister of the `SetRequired` type.
6
+ Create a type that makes the given keys optional, while keeping the remaining keys as is.
7
7
 
8
8
  Use-case: You want to define a single model where the only thing that changes is whether or not some of the keys are optional.
9
9
 
@@ -18,11 +18,7 @@ type Foo = {
18
18
  };
19
19
 
20
20
  type SomeOptional = SetOptional<Foo, 'b' | 'c'>;
21
- // type SomeOptional = {
22
- // a: number;
23
- // b?: string; // Was already optional and still is.
24
- // c?: boolean; // Is now optional.
25
- // }
21
+ //=> {a: number; b?: string; c?: boolean}
26
22
  ```
27
23
 
28
24
  @category Object
@@ -36,10 +32,10 @@ export type SetOptional<BaseType, Keys extends keyof BaseType> =
36
32
  type _SetOptional<BaseType, Keys extends keyof BaseType> =
37
33
  BaseType extends unknown // To distribute `BaseType` when it's a union type.
38
34
  ? Simplify<
39
- // Pick just the keys that are readonly from the base type.
40
- Except<BaseType, Keys> &
41
- // Pick the keys that should be mutable from the base type and make them mutable.
42
- Partial<HomomorphicPick<BaseType, Keys>>
35
+ // Pick just the keys that are readonly from the base type.
36
+ Except<BaseType, Keys>
37
+ // Pick the keys that should be mutable from the base type and make them mutable.
38
+ & Partial<HomomorphicPick<BaseType, Keys>>
43
39
  >
44
40
  : never;
45
41
 
@@ -38,14 +38,14 @@ type MergeObjectToArray<TArray extends UnknownArray, TObject, TArrayCopy extends
38
38
  : K extends keyof TObject ? TObject[K] : TArray[K]
39
39
  }
40
40
  : TObject extends object
41
- // If `TObject` is a object witch key is number like `{0: string, 1: number}`
41
+ // If `TObject` is an object with number keys like `{0: string, 1: number}`
42
42
  ? {
43
43
  [K in keyof TArray]:
44
44
  K extends `${infer NumberK extends number}`
45
45
  ? NumberK extends keyof TObject ? TObject[NumberK] : TArray[K]
46
46
  : number extends K
47
47
  // If array key `K` is `number`, means it's a rest parameter, we should set the rest parameter type to corresponding type in `TObject`.
48
- // example: `MergeObjectToParamterArray<[string, ...boolean[]], {1: number}>` => `[string, ...number[]]`
48
+ // example: `MergeObjectToArray<[string, ...boolean[]], {1: number}>` => `[string, ...number[]]`
49
49
  ? StaticPartOfArray<TArrayCopy>['length'] extends keyof TObject
50
50
  ? TObject[StaticPartOfArray<TArrayCopy>['length']]
51
51
  : TArray[K]
@@ -3,7 +3,7 @@ import type {HomomorphicPick} from './internal/index.d.ts';
3
3
  import type {Simplify} from './simplify.d.ts';
4
4
 
5
5
  /**
6
- Create a type that makes the given keys readonly. The remaining keys are kept as is.
6
+ Create a type that makes the given keys readonly, while keeping the remaining keys as is.
7
7
 
8
8
  Use-case: You want to define a single model where the only thing that changes is whether or not some of the keys are readonly.
9
9
 
@@ -18,11 +18,7 @@ type Foo = {
18
18
  };
19
19
 
20
20
  type SomeReadonly = SetReadonly<Foo, 'b' | 'c'>;
21
- // type SomeReadonly = {
22
- // a: number;
23
- // readonly b: string; // Was already readonly and still is.
24
- // readonly c: boolean; // Is now readonly.
25
- // }
21
+ //=> {a: number; readonly b: string; readonly c: boolean}
26
22
  ```
27
23
 
28
24
  @category Object
@@ -36,8 +32,8 @@ export type SetReadonly<BaseType, Keys extends keyof BaseType> =
36
32
  export type _SetReadonly<BaseType, Keys extends keyof BaseType> =
37
33
  BaseType extends unknown // To distribute `BaseType` when it's a union type.
38
34
  ? Simplify<
39
- Except<BaseType, Keys> &
40
- Readonly<HomomorphicPick<BaseType, Keys>>
35
+ Except<BaseType, Keys>
36
+ & Readonly<HomomorphicPick<BaseType, Keys>>
41
37
  >
42
38
  : never;
43
39
 
@@ -1,14 +1,15 @@
1
1
  import type {IsAny} from './is-any.d.ts';
2
- import type {NonRecursiveType, StringToNumber} from './internal/index.d.ts';
2
+ import type {NonRecursiveType} from './internal/index.d.ts';
3
3
  import type {Paths} from './paths.d.ts';
4
4
  import type {SetRequired} from './set-required.d.ts';
5
5
  import type {SimplifyDeep} from './simplify-deep.d.ts';
6
6
  import type {UnionToTuple} from './union-to-tuple.d.ts';
7
7
  import type {RequiredDeep} from './required-deep.d.ts';
8
8
  import type {UnknownArray} from './unknown-array.d.ts';
9
+ import type {StringToNumber} from './string-to-number.d.ts';
9
10
 
10
11
  /**
11
- Create a type that makes the given keys required. You can specify deeply nested key paths. The remaining keys are kept as is.
12
+ Create a type that makes the given keys required, with support for deeply nested key paths, while keeping the remaining keys as is.
12
13
 
13
14
  Use-case: Selectively make nested properties required in complex types like models.
14
15