type-fest 5.3.1 → 5.4.1

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 (53) hide show
  1. package/index.d.ts +3 -0
  2. package/package.json +4 -4
  3. package/readme.md +5 -0
  4. package/source/all-extend.d.ts +9 -6
  5. package/source/array-reverse.d.ts +84 -0
  6. package/source/array-slice.d.ts +1 -1
  7. package/source/array-splice.d.ts +3 -3
  8. package/source/conditional-pick-deep.d.ts +1 -1
  9. package/source/conditional-simplify-deep.d.ts +3 -3
  10. package/source/distributed-omit.d.ts +4 -4
  11. package/source/distributed-pick.d.ts +5 -5
  12. package/source/exact.d.ts +1 -1
  13. package/source/except.d.ts +5 -5
  14. package/source/exclusify-union.d.ts +41 -7
  15. package/source/fixed-length-array.d.ts +6 -6
  16. package/source/get.d.ts +9 -3
  17. package/source/int-closed-range.d.ts +2 -2
  18. package/source/int-range.d.ts +2 -2
  19. package/source/internal/object.d.ts +25 -1
  20. package/source/is-literal.d.ts +3 -2
  21. package/source/is-never.d.ts +2 -2
  22. package/source/is-unknown.d.ts +1 -1
  23. package/source/jsonifiable.d.ts +3 -5
  24. package/source/key-as-string.d.ts +1 -1
  25. package/source/merge-deep.d.ts +9 -9
  26. package/source/merge-exclusive.d.ts +3 -3
  27. package/source/merge.d.ts +4 -1
  28. package/source/non-empty-string.d.ts +3 -3
  29. package/source/non-empty-tuple.d.ts +2 -2
  30. package/source/numeric.d.ts +3 -3
  31. package/source/object-merge.d.ts +194 -0
  32. package/source/omit-deep.d.ts +6 -22
  33. package/source/omit-index-signature.d.ts +8 -4
  34. package/source/override-properties.d.ts +1 -1
  35. package/source/paths.d.ts +1 -1
  36. package/source/readonly-tuple.d.ts +2 -2
  37. package/source/required-deep.d.ts +2 -1
  38. package/source/schema.d.ts +10 -7
  39. package/source/set-non-nullable-deep.d.ts +1 -1
  40. package/source/set-parameter-type.d.ts +7 -7
  41. package/source/set-required-deep.d.ts +1 -7
  42. package/source/set-return-type.d.ts +1 -1
  43. package/source/split-on-rest-element.d.ts +2 -2
  44. package/source/subtract.d.ts +1 -1
  45. package/source/sum.d.ts +1 -1
  46. package/source/tuple-of.d.ts +1 -1
  47. package/source/tuple-to-object.d.ts +6 -6
  48. package/source/tuple-to-union.d.ts +1 -1
  49. package/source/union-to-intersection.d.ts +1 -1
  50. package/source/unknown-record.d.ts +6 -6
  51. package/source/unwrap-partial.d.ts +33 -0
  52. package/source/value-of.d.ts +2 -2
  53. package/source/words.d.ts +2 -2
@@ -33,7 +33,7 @@ type MergeDeepRecordProperty<
33
33
  Source,
34
34
  Options extends MergeDeepInternalOptions,
35
35
  > = undefined extends Source
36
- ? MergeDeepOrReturn<Source, Exclude<Destination, undefined>, Exclude<Source, undefined>, Options> | undefined
36
+ ? MergeDeepOrReturn<Source, Exclude<Destination, undefined>, Exclude<Source, undefined>, Options> | (undefined extends Destination ? undefined : never)
37
37
  : MergeDeepOrReturn<Source, Destination, Source, Options>;
38
38
 
39
39
  /**
@@ -58,7 +58,7 @@ type DoMergeDeepRecord<
58
58
  }
59
59
  // Case in rule 3: Both the source and the destination contain the key.
60
60
  & {
61
- [Key in keyof Source as Key extends keyof Destination ? Key : never]: MergeDeepRecordProperty<Destination[Key], Source[Key], Options>;
61
+ [Key in keyof Source as Key extends keyof Destination ? Key : never]: MergeDeepRecordProperty<Required<Destination>[Key], Required<Source>[Key], Options>;
62
62
  };
63
63
 
64
64
  /**
@@ -446,25 +446,25 @@ type Foo = {foo: 'foo'; fooBar: string[]};
446
446
  type Bar = {bar: 'bar'; fooBar: number[]};
447
447
 
448
448
  type FooBar = MergeDeep<Foo, Bar>;
449
- // { foo: "foo"; bar: "bar"; fooBar: number[]}
449
+ //=> {foo: 'foo'; bar: 'bar'; fooBar: number[]}
450
450
 
451
451
  type FooBarSpread = MergeDeep<Foo, Bar, {arrayMergeMode: 'spread'}>;
452
- // { foo: "foo"; bar: "bar"; fooBar: (string | number)[]}
452
+ //=> {foo: 'foo'; bar: 'bar'; fooBar: (string | number)[]}
453
453
 
454
454
  type FooBarArray = MergeDeep<Foo[], Bar[]>;
455
- // (Foo | Bar)[]
455
+ //=> (Foo | Bar)[]
456
456
 
457
457
  type FooBarArrayDeep = MergeDeep<Foo[], Bar[], {recurseIntoArrays: true}>;
458
- // FooBar[]
458
+ //=> {foo: 'foo'; bar: 'bar'; fooBar: number[]}[]
459
459
 
460
460
  type FooBarArraySpreadDeep = MergeDeep<Foo[], Bar[], {recurseIntoArrays: true; arrayMergeMode: 'spread'}>;
461
- // FooBarSpread[]
461
+ //=> {foo: 'foo'; bar: 'bar'; fooBar: (string | number)[]}[]
462
462
 
463
463
  type FooBarTupleDeep = MergeDeep<[Foo, true, 42], [Bar, 'life'], {recurseIntoArrays: true}>;
464
- // [FooBar, 'life', 42]
464
+ //=> [{foo: 'foo'; bar: 'bar'; fooBar: number[]}, 'life', 42]
465
465
 
466
466
  type FooBarTupleWithArrayDeep = MergeDeep<[Foo[], true], [Bar[], 'life', 42], {recurseIntoArrays: true}>;
467
- // [FooBar[], 'life', 42]
467
+ //=> [{foo: 'foo'; bar: 'bar'; fooBar: number[]}[], 'life', 42]
468
468
  ```
469
469
 
470
470
  @example
@@ -25,14 +25,14 @@ type ExclusiveOptions = MergeExclusive<ExclusiveVariation1, ExclusiveVariation2>
25
25
  let exclusiveOptions: ExclusiveOptions;
26
26
 
27
27
  exclusiveOptions = {exclusive1: true};
28
- //=> Works
28
+ // Works
29
29
 
30
30
  exclusiveOptions = {exclusive2: 'hi'};
31
- //=> Works
31
+ // Works
32
32
 
33
33
  // @ts-expect-error
34
34
  exclusiveOptions = {exclusive1: true, exclusive2: 'hi'};
35
- //=> Error
35
+ // Error
36
36
  ```
37
37
 
38
38
  @category Object
package/source/merge.d.ts CHANGED
@@ -29,7 +29,7 @@ type Bar = {
29
29
  };
30
30
 
31
31
  export type FooBar = Merge<Foo, Bar>;
32
- // => {
32
+ //=> {
33
33
  // [x: string]: unknown;
34
34
  // [x: number]: number;
35
35
  // [x: symbol]: unknown;
@@ -39,6 +39,9 @@ export type FooBar = Merge<Foo, Bar>;
39
39
  // }
40
40
  ```
41
41
 
42
+ Note: If you want a merge type that more accurately reflects the runtime behavior of object spread or `Object.assign`, refer to the {@link ObjectMerge} type.
43
+
44
+ @see {@link ObjectMerge}
42
45
  @category Object
43
46
  */
44
47
  export type Merge<Destination, Source> =
@@ -13,16 +13,16 @@ import type {NonEmptyString} from 'type-fest';
13
13
  declare function foo<T extends string>(string: NonEmptyString<T>): void;
14
14
 
15
15
  foo('a');
16
- //=> OK
16
+ // OK
17
17
 
18
18
  // @ts-expect-error
19
19
  foo('');
20
- //=> Error: Argument of type '""' is not assignable to parameter of type 'never'.
20
+ // Error: Argument of type '""' is not assignable to parameter of type 'never'.
21
21
 
22
22
  declare const someString: string;
23
23
  // @ts-expect-error
24
24
  foo(someString);
25
- //=> Error: Argument of type 'string' is not assignable to parameter of type 'never'.
25
+ // Error: Argument of type 'string' is not assignable to parameter of type 'never'.
26
26
  ```
27
27
 
28
28
  @category String
@@ -8,11 +8,11 @@ import type {NonEmptyTuple} from 'type-fest';
8
8
  const sum = (...numbers: NonEmptyTuple<number>) => numbers.reduce((total, value) => total + value, 0);
9
9
 
10
10
  sum(1, 2, 3);
11
- //=> 6
11
+ // Ok
12
12
 
13
13
  // @ts-expect-error
14
14
  sum();
15
- //=> Error: Expected at least 1 arguments, but got 0.
15
+ // Error: Expected at least 1 arguments, but got 0.
16
16
  ```
17
17
 
18
18
  @see {@link RequireAtLeastOne} for objects
@@ -74,13 +74,13 @@ type Float = Integer<1.5>;
74
74
  // Supports non-decimal numbers
75
75
 
76
76
  type OctalInteger = Integer<0o10>;
77
- //=> 0o10
77
+ //=> 8
78
78
 
79
79
  type BinaryInteger = Integer<0b10>;
80
- //=> 0b10
80
+ //=> 2
81
81
 
82
82
  type HexadecimalInteger = Integer<0x10>;
83
- //=> 0x10
83
+ //=> 16
84
84
  ```
85
85
 
86
86
  @example
@@ -0,0 +1,194 @@
1
+ import type {If} from './if.d.ts';
2
+ import type {NormalizedKeys} from './internal/object.d.ts';
3
+ import type {IfNotAnyOrNever, IsExactOptionalPropertyTypesEnabled, MapsSetsOrArrays} from './internal/type.d.ts';
4
+ import type {IsNever} from './is-never.d.ts';
5
+ import type {IsOptionalKeyOf} from './is-optional-key-of.d.ts';
6
+ import type {OmitIndexSignature} from './omit-index-signature.d.ts';
7
+ import type {PickIndexSignature} from './pick-index-signature.d.ts';
8
+ import type {RequiredKeysOf} from './required-keys-of.d.ts';
9
+ import type {Simplify} from './simplify.d.ts';
10
+
11
+ /**
12
+ Merge two object types into a new object type, where keys from the second override keys from the first.
13
+
14
+ @example
15
+ ```ts
16
+ import type {ObjectMerge} from 'type-fest';
17
+
18
+ type PartialOverride = ObjectMerge<{foo: string; bar: string}, {foo: number; baz: number}>;
19
+ //=> {foo: number; baz: number; bar: string}
20
+
21
+ type CompleteOverride = ObjectMerge<{foo: string; bar: number}, {foo: number; bar: string; baz: boolean}>;
22
+ //=> {foo: number; bar: string; baz: boolean}
23
+
24
+ type NoOverride = ObjectMerge<{foo: string; bar: number}, {baz: boolean; qux: bigint}>;
25
+ //=> {baz: boolean; qux: bigint; foo: string; bar: number}
26
+ ```
27
+
28
+ Use-cases:
29
+
30
+ Can be used to accurately type object spread and `Object.assign`. The built-in inference for these operations can sometimes be unsound, especially when index signatures are involved.
31
+
32
+ In the following example, both object spread and `Object.assign` produce a type that allows unsafe usage, whereas `ObjectMerge` produces a type that prevents this unsafe access.
33
+
34
+ @example
35
+ ```ts
36
+ import type {ObjectMerge} from 'type-fest';
37
+
38
+ const left: {a: string} = {a: '1'};
39
+ const right: {[x: string]: number} = {a: 1};
40
+
41
+ const inferred = {...left, ...right};
42
+ //=> {a: string}
43
+
44
+ inferred.a.toUpperCase(); // No compile time error, but fails at runtime.
45
+
46
+ const objectAssign = Object.assign(left, right);
47
+ //=> {a: string} & {[x: string]: number}
48
+
49
+ objectAssign.a.toUpperCase(); // No compile time error, but fails at runtime.
50
+
51
+ declare const objectMerge: ObjectMerge<typeof left, typeof right>;
52
+ //=> {[x: string]: string | number; a: string | number}
53
+
54
+ // @ts-expect-error
55
+ objectMerge.a.toUpperCase(); // Correctly errors at compile time.
56
+ ```
57
+
58
+ Can be used to merge generic type arguments.
59
+
60
+ In the following example, object spread without `ObjectMerge` produces an intersection type that is not particularly usable, whereas `ObjectMerge` produces a correctly merged and usable result.
61
+
62
+ @example
63
+ ```ts
64
+ import type {ObjectMerge} from 'type-fest';
65
+
66
+ function withoutObjectMerge<T extends object, U extends object>(left: T, right: U) {
67
+ return {...left, ...right};
68
+ }
69
+
70
+ const result1 = withoutObjectMerge({a: 1}, {a: 'one'});
71
+ //=> {a: number} & {a: string}
72
+
73
+ const {a} = result1;
74
+ //=> never
75
+
76
+ function withObjectMerge<T extends object, U extends object>(left: T, right: U) {
77
+ return {...left, ...right} as unknown as ObjectMerge<T, U>;
78
+ }
79
+
80
+ const result2 = withObjectMerge({b: 1}, {b: 'one'});
81
+ //=> {b: string}
82
+
83
+ const {b} = result2;
84
+ //=> string
85
+ ```
86
+
87
+ Note: If you want a simple merge where properties from the second object always override properties from the first object without considering runtime implications, refer to the {@link Merge} type.
88
+
89
+ @see {@link Merge}
90
+ @category Object
91
+ */
92
+ export type ObjectMerge<First extends object, Second extends object> =
93
+ IfNotAnyOrNever<First, IfNotAnyOrNever<Second, First extends unknown // For distributing `First`
94
+ ? Second extends unknown // For distributing `Second`
95
+ ? First extends MapsSetsOrArrays
96
+ ? unknown
97
+ : Second extends MapsSetsOrArrays
98
+ ? unknown
99
+ : _ObjectMerge<
100
+ First,
101
+ Second,
102
+ NormalizedLiteralKeys<First>,
103
+ NormalizedLiteralKeys<Second>,
104
+ IsExactOptionalPropertyTypesEnabled extends true ? Required<First> : First,
105
+ IsExactOptionalPropertyTypesEnabled extends true ? Required<Second> : Second
106
+ >
107
+ : never // Should never happen
108
+ : never>, First & Second>; // Should never happen
109
+
110
+ type _ObjectMerge<
111
+ First extends object,
112
+ Second extends object,
113
+ NormalizedFirstLiteralKeys extends PropertyKey,
114
+ NormalizedSecondLiteralKeys extends PropertyKey,
115
+ NormalizedFirst extends object,
116
+ NormalizedSecond extends object,
117
+ > = Simplify<{
118
+ // Map over literal keys of `Second`, except those that are optional and also present in `First`.
119
+ -readonly [P in keyof Second as P extends NormalizedSecondLiteralKeys
120
+ ? P extends NormalizedFirstLiteralKeys
121
+ ? If<IsOptionalKeyOf<Second, P>, never, P>
122
+ : P
123
+ : never]:
124
+ | Second[P]
125
+ | (P extends NormalizedKeys<keyof PickIndexSignature<First>>
126
+ ? If<IsOptionalKeyOf<Second, P>, First[NormalizedKeys<P> & keyof First], never>
127
+ : never)
128
+ } & {
129
+ // Map over literal keys of `First`, except those that are not present in `Second`.
130
+ -readonly [P in keyof First as P extends NormalizedFirstLiteralKeys
131
+ ? P extends NormalizedSecondLiteralKeys
132
+ ? never
133
+ : P
134
+ : never]:
135
+ | First[P]
136
+ // If there's a matching index signature in `Second`, then add the type for it as well,
137
+ // for example, in `ObjectMerge<{a: string}, {[x: string]: number}>`, `a` is of type `string | number`.
138
+ | (P extends NormalizedKeys<keyof Second>
139
+ ? Second[NormalizedKeys<P> & keyof Second]
140
+ : never);
141
+ } & {
142
+ // Map over non-literal keys of `Second`.
143
+ -readonly [P in keyof Second as P extends NormalizedSecondLiteralKeys ? never : P]:
144
+ | Second[P]
145
+ // If there's a matching key in `First`, then add the type for it as well,
146
+ // for example, in `ObjectMerge<{a: number}, {[x: string]: string}>`,
147
+ // the resulting type is `{[x: string]: number | string; a: number | string}`.
148
+ // But, exclude keys from `First` that would surely get overwritten,
149
+ // for example, in `ObjectMerge<{a: number}, {[x: string]: string; a: string}>`,
150
+ // `a` from `First` would get overwritten by `a` from `Second`, so don't add type for it.
151
+ | (NormalizedKeys<P> & Exclude<keyof First, NormalizedKeys<RequiredKeysOf<OmitIndexSignature<Second>>>> extends infer NonOverwrittenKeysOfFirst
152
+ ? If<IsNever<NonOverwrittenKeysOfFirst>, // This check is required because indexing with `never` doesn't always yield `never`, for example, `{[x: string]: number}[never]` results in `number`.
153
+ never,
154
+ NormalizedFirst[NonOverwrittenKeysOfFirst & keyof NormalizedFirst]>
155
+ : never); // Should never happen
156
+ } & {
157
+ // Map over non-literal keys of `First`.
158
+ -readonly [P in keyof First as P extends NormalizedFirstLiteralKeys ? never : P]:
159
+ | First[P]
160
+ | If<IsNever<NormalizedKeys<P> & keyof Second>, // This check is required because indexing with `never` doesn't always yield `never`, for example, `{[x: string]: number}[never]` results in `number`.
161
+ never,
162
+ NormalizedSecond[NormalizedKeys<P> & keyof NormalizedSecond]>;
163
+ } & {
164
+ // Handle optional keys of `Second` that are also present in `First`.
165
+ // Map over `First` instead of `Second` because the modifier is in accordance with `First`.
166
+ -readonly [P in keyof First as P extends NormalizedFirstLiteralKeys
167
+ ? P extends NormalizedSecondLiteralKeys
168
+ ? If<IsOptionalKeyOf<Second, NormalizedKeys<P> & keyof Second>, P, never>
169
+ : never
170
+ : never]:
171
+ | First[P]
172
+ | NormalizedSecond[NormalizedKeys<P> & keyof NormalizedSecond]
173
+ }>;
174
+
175
+ /**
176
+ Get literal keys of a type, including both string and number representations wherever applicable.
177
+
178
+ @example
179
+ ```ts
180
+ type A = NormalizedLiteralKeys<{0: string; '1'?: number; foo: boolean}>;
181
+ //=> 0 | '0' | 1 | '1' | 'foo'
182
+
183
+ type B = NormalizedLiteralKeys<{[x: string]: string | number; 0: string; '1'?: number}>;
184
+ //=> 0 | '0' | 1 | '1'
185
+
186
+ type C = NormalizedLiteralKeys<{[x: string]: unknown}>;
187
+ //=> never
188
+ ```
189
+ */
190
+ type NormalizedLiteralKeys<Type> = Type extends unknown // For distributing `Type`
191
+ ? NormalizedKeys<keyof OmitIndexSignature<Type>>
192
+ : never; // Should never happen
193
+
194
+ export {};
@@ -5,6 +5,7 @@ import type {IsNever} from './is-never.d.ts';
5
5
  import type {LiteralUnion} from './literal-union.d.ts';
6
6
  import type {Paths} from './paths.d.ts';
7
7
  import type {SimplifyDeep} from './simplify-deep.d.ts';
8
+ import type {Simplify} from './simplify.d.ts';
8
9
  import type {UnionToTuple} from './union-to-tuple.d.ts';
9
10
  import type {UnknownArray} from './unknown-array.d.ts';
10
11
 
@@ -33,11 +34,7 @@ type Info = {
33
34
  };
34
35
 
35
36
  type UsefulInfo = OmitDeep<Info, 'userInfo.uselessInfo'>;
36
- //=> {
37
- // userInfo: {
38
- // name: string;
39
- // };
40
- // };
37
+ //=> {userInfo: {name: string}}
41
38
 
42
39
  // Supports removing multiple paths
43
40
  type Info1 = {
@@ -51,15 +48,11 @@ type Info1 = {
51
48
  };
52
49
 
53
50
  type UsefulInfo1 = OmitDeep<Info1, 'userInfo.uselessInfo' | 'userInfo.uselessField'>;
54
- //=> {
55
- // userInfo: {
56
- // name: string;
57
- // };
58
- // };
51
+ //=> {userInfo: {name: string}}
59
52
 
60
53
  // Supports array
61
54
  type A = OmitDeep<[1, 'foo', 2], '1'>;
62
- //=> [1, unknown, 2];
55
+ //=> [1, unknown, 2]
63
56
 
64
57
  // Supports recursing into array
65
58
 
@@ -76,16 +69,7 @@ type Info2 = {
76
69
  };
77
70
 
78
71
  type AddressInfo = OmitDeep<Info2, 'address.1.foo'>;
79
- //=> {
80
- // address: [
81
- // {
82
- // street: string;
83
- // },
84
- // {
85
- // street2: string;
86
- // };
87
- // ];
88
- // };
72
+ //=> {address: [{street: string}, {street2: string}]}
89
73
  ```
90
74
 
91
75
  @category Object
@@ -135,7 +119,7 @@ P extends `${infer RecordKeyInPath}.${infer SubPath}`
135
119
  ? IsNever<Key> extends true
136
120
  ? ObjectT
137
121
  : Key extends PropertyKey
138
- ? Omit<ObjectT, Key>
122
+ ? Simplify<Omit<ObjectT, Key>> // `Simplify` to prevent `Omit` from appearing in the resulting type
139
123
  : ObjectT
140
124
  : ObjectT;
141
125
 
@@ -17,7 +17,7 @@ const indexed: Record<string, unknown> = {}; // Allowed
17
17
 
18
18
  // @ts-expect-error
19
19
  const keyed: Record<'foo', unknown> = {}; // Error
20
- // => TS2739: Type '{}' is missing the following properties from type 'Record<"foo" | "bar", unknown>': foo, bar
20
+ // TS2739: Type '{}' is missing the following properties from type 'Record<"foo" | "bar", unknown>': foo, bar
21
21
  ```
22
22
 
23
23
  Instead of causing a type error like the above, you can also use a [conditional type](https://www.typescriptlang.org/docs/handbook/2/conditional-types.html) to test whether a type is assignable to another:
@@ -26,12 +26,16 @@ Instead of causing a type error like the above, you can also use a [conditional
26
26
  type Indexed = {} extends Record<string, unknown>
27
27
  ? '✅ `{}` is assignable to `Record<string, unknown>`'
28
28
  : '❌ `{}` is NOT assignable to `Record<string, unknown>`';
29
- // => '✅ `{}` is assignable to `Record<string, unknown>`'
29
+
30
+ type IndexedResult = Indexed;
31
+ //=> '✅ `{}` is assignable to `Record<string, unknown>`'
30
32
 
31
33
  type Keyed = {} extends Record<'foo' | 'bar', unknown>
32
34
  ? '✅ `{}` is assignable to `Record<\'foo\' | \'bar\', unknown>`'
33
35
  : '❌ `{}` is NOT assignable to `Record<\'foo\' | \'bar\', unknown>`';
34
- // => "❌ `{}` is NOT assignable to `Record<'foo' | 'bar', unknown>`"
36
+
37
+ type KeyedResult = Keyed;
38
+ //=> '❌ `{}` is NOT assignable to `Record<\'foo\' | \'bar\', unknown>`'
35
39
  ```
36
40
 
37
41
  Using a [mapped type](https://www.typescriptlang.org/docs/handbook/2/mapped-types.html#further-exploration), you can then check for each `KeyType` of `ObjectType`...
@@ -79,7 +83,7 @@ type Example = {
79
83
  };
80
84
 
81
85
  type ExampleWithoutIndexSignatures = OmitIndexSignature<Example>;
82
- // => { foo: 'bar'; qux?: 'baz' | undefined; }
86
+ //=> {foo: 'bar'; qux?: 'baz'}
83
87
  ```
84
88
 
85
89
  @see {@link PickIndexSignature}
@@ -15,7 +15,7 @@ type Foo = {
15
15
  };
16
16
 
17
17
  type Bar = OverrideProperties<Foo, {b: number}>;
18
- //=> {a: string, b: number}
18
+ //=> {a: string; b: number}
19
19
 
20
20
  // @ts-expect-error
21
21
  type Baz = OverrideProperties<Foo, {c: number}>;
package/source/paths.d.ts CHANGED
@@ -92,7 +92,7 @@ export type PathsOptions = {
92
92
  };
93
93
 
94
94
  type AllPaths = Paths<ArrayExample, {leavesOnly: false}>;
95
- //=> 'array' | `array.${number}` | `array.${number}.foo` | 'tuple' | 'tuple.0' | 'tuple.1' | 'tuple.1.bar'
95
+ //=> 'array' | 'tuple' | `array.${number}` | `array.${number}.foo` | 'tuple.0' | 'tuple.1' | 'tuple.1.bar'
96
96
 
97
97
  type LeafPaths = Paths<ArrayExample, {leavesOnly: true}>;
98
98
  //=> `array.${number}.foo` | 'tuple.0' | 'tuple.1.bar'
@@ -18,11 +18,11 @@ const guestFencingTeam: FencingTeam = ['Josh', 'Michael', 'Robert'];
18
18
 
19
19
  // @ts-expect-error
20
20
  const homeFencingTeam: FencingTeam = ['George', 'John'];
21
- //=> Error: Type '[string, string]' is not assignable to type 'readonly [string, string, string]'.
21
+ // Error: Type '[string, string]' is not assignable to type 'readonly [string, string, string]'.
22
22
 
23
23
  // @ts-expect-error
24
24
  guestFencingTeam.push('Sam');
25
- //=> Error: Property 'push' does not exist on type 'readonly [string, string, string]'.
25
+ // Error: Property 'push' does not exist on type 'readonly [string, string, string]'.
26
26
  ```
27
27
 
28
28
  @deprecated This type will be removed in the next major version. Use the built-in `Readonly` type in combination with the {@link TupleOf} type instead, like `Readonly<TupleOf<Length, Element>>`.
@@ -1,5 +1,6 @@
1
1
  import type {BuiltIns, HasMultipleCallSignatures} from './internal/index.d.ts';
2
2
  import type {IsNever} from './is-never.d.ts';
3
+ import type {Simplify} from './simplify.d.ts';
3
4
 
4
5
  /**
5
6
  Create a type from another type with all keys and nested keys set to required.
@@ -65,7 +66,7 @@ export type RequiredDeep<T> = T extends BuiltIns
65
66
  ? T
66
67
  : ((...arguments_: Parameters<T>) => ReturnType<T>) & RequiredObjectDeep<T>
67
68
  : T extends object
68
- ? RequiredObjectDeep<T>
69
+ ? Simplify<RequiredObjectDeep<T>> // `Simplify` to prevent `RequiredObjectDeep` from appearing in the resulting type
69
70
  : unknown;
70
71
 
71
72
  type RequiredObjectDeep<ObjectType extends object> = {
@@ -24,15 +24,18 @@ export type SchemaOptions = {
24
24
 
25
25
  type ParticipantsWithMetadata = Schema<Participants, {id: number; name: string}, {recurseIntoArrays: true}>;
26
26
  //=> {
27
- // attendees: Array<{id: number; name: string}>;
28
- // speakers: Array<{id: number; name: string}>;
29
- // };
27
+ // attendees: {
28
+ // id: number;
29
+ // name: string;
30
+ // }[];
31
+ // speakers: {
32
+ // id: number;
33
+ // name: string;
34
+ // }[];
35
+ // }
30
36
 
31
37
  type ParticipantsCount = Schema<Participants, number, {recurseIntoArrays: false}>;
32
- //=> {
33
- // attendees: number;
34
- // speakers: number;
35
- // };
38
+ //=> {attendees: number; speakers: number}
36
39
  ```
37
40
 
38
41
  @default true
@@ -37,7 +37,7 @@ type UpdatedUser = SetNonNullableDeep<User, 'address.street' | 'contact.email' |
37
37
  // email?: string;
38
38
  // phone: string;
39
39
  // };
40
- // };
40
+ // }
41
41
  ```
42
42
 
43
43
  @example
@@ -64,11 +64,11 @@ Note:
64
64
  import type {SetParameterType} from 'type-fest';
65
65
 
66
66
  const fn = (a: number) => a;
67
- //=> fn: (a: number) => number;
67
+ //=> (a: number) => number
68
68
 
69
69
  // We change type of `a` to `string`, but return type is still `number`.
70
70
  type Fn = SetParameterType<typeof fn, {0: string}>;
71
- //=> (a: string) => number;
71
+ //=> (a: string) => number
72
72
  ```
73
73
 
74
74
  Use-case:
@@ -87,25 +87,25 @@ type Data = SuccessData | ErrorData;
87
87
  type HandleMessage = (data: Data, message: string, ...arguments_: any[]) => void;
88
88
 
89
89
  type HandleOk = SetParameterType<HandleMessage, {0: SuccessData; 1: 'ok'}>;
90
- //=> (data: SuccessData, message: 'ok', ...arguments_: any[]) => void;
90
+ //=> (data: SuccessData, message: 'ok', ...arguments_: any[]) => void
91
91
 
92
92
  // Another way to define the parameters to replace.
93
93
  type HandleError = SetParameterType<HandleMessage, [data: ErrorData, message: 'error']>;
94
- //=> (data: ErrorData, message: 'error', ...arguments_: any[]) => void;
94
+ //=> (data: ErrorData, message: 'error', ...arguments_: any[]) => void
95
95
 
96
96
  // Change single parameter type.
97
97
  type HandleWarn = SetParameterType<HandleMessage, {1: 'warn'}>;
98
- //=> (data: Data, message: 'warn', ...arguments_: any[]) => void;
98
+ //=> (data: Data, message: 'warn', ...arguments_: any[]) => void
99
99
 
100
100
  // Change rest parameter type.
101
101
 
102
102
  // Way 1: Input full parameter type.
103
103
  type HandleLog = SetParameterType<HandleMessage, [data: Data, message: 'log', ...arguments_: string[]]>;
104
- //=> (data: Data, message: 'log', ...arguments_: string[]) => void;
104
+ //=> (data: Data, message: 'log', ...arguments_: string[]) => void
105
105
 
106
106
  // Way 2: Input rest parameter type by Object index.
107
107
  type HandleLog2 = SetParameterType<HandleMessage, {2: string}>;
108
- //=> (data: Data, message: string, ...arguments_: string[]) => void;
108
+ //=> (data: Data, message: string, ...arguments_: string[]) => void
109
109
  ```
110
110
 
111
111
  @category Function
@@ -25,13 +25,7 @@ type Foo = {
25
25
  };
26
26
 
27
27
  type SomeRequiredDeep = SetRequiredDeep<Foo, 'a' | `c.${number}.d`>;
28
- //=> {
29
- // a: number; // Is now required
30
- // b?: string;
31
- // c?: {
32
- // d: number; // Is now required
33
- // }[];
34
- // }
28
+ //=> {b?: string; c?: {d: number}[]; a: number}
35
29
 
36
30
  // Set specific indices in an array to be required.
37
31
  type ArrayExample = SetRequiredDeep<{a: [number?, number?, number?]}, 'a.0' | 'a.1'>;
@@ -12,7 +12,7 @@ import type {SetReturnType} from 'type-fest';
12
12
  type MyFunctionThatCanThrow = (foo: string, bar: number) => boolean;
13
13
 
14
14
  type MyWrappedFunction = SetReturnType<MyFunctionThatCanThrow, ReturnType<MyFunctionThatCanThrow> | undefined>;
15
- //=> (foo: string, bar: number) => boolean | undefined;
15
+ //=> (foo: string, bar: number) => boolean | undefined
16
16
  ```
17
17
 
18
18
  @category Function
@@ -50,10 +50,10 @@ type T3 = SplitOnRestElement<[number, string?]>;
50
50
  //=> [[number, string?], [], []]
51
51
 
52
52
  type T4 = SplitOnRestElement<[number, string?], {preserveOptionalModifier: false}>;
53
- //=> [[number, string], [], []] or [[number, string | undefined], [], []]
53
+ //=> [[number, string], [], []]
54
54
 
55
55
  type T5 = SplitOnRestElement<readonly [string?, ...number[]], {preserveOptionalModifier: false}>;
56
- //=> readonly [[string], number[], []] or readonly [[string | undefined], number[], []]
56
+ //=> readonly [[string], number[], []]
57
57
  ```
58
58
 
59
59
  @see {@link ExtractRestElement}
@@ -26,7 +26,7 @@ type D = Subtract<18, 96>;
26
26
  //=> -78
27
27
 
28
28
  type E = Subtract<PositiveInfinity, 9999>;
29
- //=> PositiveInfinity
29
+ //=> Infinity
30
30
 
31
31
  type F = Subtract<PositiveInfinity, PositiveInfinity>;
32
32
  //=> number
package/source/sum.d.ts CHANGED
@@ -23,7 +23,7 @@ type C = Sum<111, -222>;
23
23
  //=> -111
24
24
 
25
25
  type D = Sum<PositiveInfinity, -9999>;
26
- //=> PositiveInfinity
26
+ //=> Infinity
27
27
 
28
28
  type E = Sum<PositiveInfinity, NegativeInfinity>;
29
29
  //=> number
@@ -30,7 +30,7 @@ type ZeroToFour = Range<0, 5>;
30
30
  //=> '0' | '1' | '2' | '3' | '4'
31
31
 
32
32
  type ThreeToEight = Range<3, 9>;
33
- //=> '3' | '4' | '5' | '6' | '7' | '8'
33
+ //=> '5' | '3' | '4' | '6' | '7' | '8'
34
34
  ```
35
35
 
36
36
  Note: If the specified length is the non-literal `number` type, the result will not be a tuple but a regular array.