type-fest 5.4.3 → 5.5.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.
- package/index.d.ts +7 -0
- package/package.json +1 -1
- package/readme.md +14 -4
- package/source/all-extend.d.ts +5 -6
- package/source/and-all.d.ts +76 -0
- package/source/and.d.ts +3 -2
- package/source/array-length.d.ts +36 -0
- package/source/array-splice.d.ts +2 -2
- package/source/conditional-pick-deep.d.ts +5 -3
- package/source/conditional-pick.d.ts +6 -4
- package/source/exclude-exactly.d.ts +57 -0
- package/source/greater-than-or-equal.d.ts +34 -1
- package/source/greater-than.d.ts +34 -1
- package/source/internal/array.d.ts +0 -7
- package/source/internal/tuple.d.ts +1 -1
- package/source/internal/type.d.ts +1 -0
- package/source/is-equal.d.ts +0 -1
- package/source/is-union.d.ts +2 -1
- package/source/less-than-or-equal.d.ts +39 -3
- package/source/less-than.d.ts +35 -3
- package/source/merge.d.ts +25 -0
- package/source/omit-deep.d.ts +1 -2
- package/source/optional.d.ts +31 -0
- package/source/or-all.d.ts +73 -0
- package/source/or.d.ts +3 -10
- package/source/package-json.d.ts +2 -2
- package/source/paths.d.ts +40 -57
- package/source/pick-deep.d.ts +6 -21
- package/source/set-non-nullable.d.ts +3 -10
- package/source/set-optional.d.ts +1 -5
- package/source/set-parameter-type.d.ts +2 -2
- package/source/set-readonly.d.ts +1 -5
- package/source/set-required.d.ts +1 -5
- package/source/shared-union-fields-deep.d.ts +1 -1
- package/source/some-extend.d.ts +113 -0
- package/source/spread.d.ts +1 -5
- package/source/tagged.d.ts +2 -2
- package/source/union-member.d.ts +65 -0
- package/source/union-to-tuple.d.ts +4 -17
- package/source/writable.d.ts +1 -5
package/source/merge.d.ts
CHANGED
|
@@ -12,6 +12,31 @@ type SimpleMerge<Destination, Source> = Simplify<{
|
|
|
12
12
|
/**
|
|
13
13
|
Merge two types into a new type. Keys of the second type overrides keys of the first type.
|
|
14
14
|
|
|
15
|
+
This is different from the TypeScript `&` (intersection) operator. With `&`, conflicting property types are intersected, which often results in `never`. For example, `{a: string} & {a: number}` makes `a` become `string & number`, which resolves to `never`. With `Merge`, the second type's keys cleanly override the first, so `Merge<{a: string}, {a: number}>` gives `{a: number}` as expected. `Merge` also produces a flattened type (via `Simplify`), making it more readable in IDE tooltips compared to `A & B`.
|
|
16
|
+
|
|
17
|
+
@example
|
|
18
|
+
```
|
|
19
|
+
import type {Merge} from 'type-fest';
|
|
20
|
+
|
|
21
|
+
type Foo = {
|
|
22
|
+
a: string;
|
|
23
|
+
b: number;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
type Bar = {
|
|
27
|
+
a: number; // Conflicts with Foo['a']
|
|
28
|
+
c: boolean;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// With `&`, `a` becomes `string & number` which is `never`. Not what you want.
|
|
32
|
+
type WithIntersection = (Foo & Bar)['a'];
|
|
33
|
+
//=> never
|
|
34
|
+
|
|
35
|
+
// With `Merge`, `a` is cleanly overridden to `number`.
|
|
36
|
+
type WithMerge = Merge<Foo, Bar>['a'];
|
|
37
|
+
//=> number
|
|
38
|
+
```
|
|
39
|
+
|
|
15
40
|
@example
|
|
16
41
|
```
|
|
17
42
|
import type {Merge} from 'type-fest';
|
package/source/omit-deep.d.ts
CHANGED
|
@@ -5,7 +5,6 @@ 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';
|
|
9
8
|
import type {UnionToTuple} from './union-to-tuple.d.ts';
|
|
10
9
|
import type {UnknownArray} from './unknown-array.d.ts';
|
|
11
10
|
|
|
@@ -119,7 +118,7 @@ P extends `${infer RecordKeyInPath}.${infer SubPath}`
|
|
|
119
118
|
? IsNever<Key> extends true
|
|
120
119
|
? ObjectT
|
|
121
120
|
: Key extends PropertyKey
|
|
122
|
-
?
|
|
121
|
+
? Omit<ObjectT, Key>
|
|
123
122
|
: ObjectT
|
|
124
123
|
: ObjectT;
|
|
125
124
|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Create a type that represents either the value or `undefined`, while stripping `null` from the type.
|
|
3
|
+
|
|
4
|
+
Use-cases:
|
|
5
|
+
- Enforcing the practice of using `undefined` instead of `null` as the "absence of value" marker.
|
|
6
|
+
- Converting APIs that return `null` (DOM, JSON, legacy libraries) to use `undefined` consistently.
|
|
7
|
+
|
|
8
|
+
@example
|
|
9
|
+
```
|
|
10
|
+
import type {Optional} from 'type-fest';
|
|
11
|
+
|
|
12
|
+
// Adds `undefined` to the type
|
|
13
|
+
type MaybeNumber = Optional<number>;
|
|
14
|
+
//=> number | undefined
|
|
15
|
+
|
|
16
|
+
// Strips `null` from the type
|
|
17
|
+
type NullableString = Optional<string | null>;
|
|
18
|
+
//=> string | undefined
|
|
19
|
+
|
|
20
|
+
type Config = {
|
|
21
|
+
name: string;
|
|
22
|
+
description: Optional<string>;
|
|
23
|
+
//=> string | undefined
|
|
24
|
+
};
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
@category Utilities
|
|
28
|
+
*/
|
|
29
|
+
export type Optional<Value> = Exclude<Value, null> | undefined;
|
|
30
|
+
|
|
31
|
+
export {};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type {SomeExtend} from './some-extend.d.ts';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
Returns a boolean for whether any of the given elements is `true`.
|
|
5
|
+
|
|
6
|
+
Use-cases:
|
|
7
|
+
- Check if at least one condition in a list of booleans is met.
|
|
8
|
+
|
|
9
|
+
@example
|
|
10
|
+
```
|
|
11
|
+
import type {OrAll} from 'type-fest';
|
|
12
|
+
|
|
13
|
+
type FFT = OrAll<[false, false, true]>;
|
|
14
|
+
//=> true
|
|
15
|
+
|
|
16
|
+
type FFF = OrAll<[false, false, false]>;
|
|
17
|
+
//=> false
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Note: When `boolean` is passed as an element, it is distributed into separate cases, and the final result is a union of those cases.
|
|
21
|
+
For example, `OrAll<[false, boolean]>` expands to `OrAll<[false, true]> | OrAll<[false, false]>`, which simplifies to `true | false` (i.e., `boolean`).
|
|
22
|
+
|
|
23
|
+
@example
|
|
24
|
+
```
|
|
25
|
+
import type {OrAll} from 'type-fest';
|
|
26
|
+
|
|
27
|
+
type A = OrAll<[false, boolean]>;
|
|
28
|
+
//=> boolean
|
|
29
|
+
|
|
30
|
+
type B = OrAll<[true, boolean]>;
|
|
31
|
+
//=> true
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Note: If `never` is passed as an element, it is treated as `false` and the result is computed accordingly.
|
|
35
|
+
|
|
36
|
+
@example
|
|
37
|
+
```
|
|
38
|
+
import type {OrAll} from 'type-fest';
|
|
39
|
+
|
|
40
|
+
type A = OrAll<[never, never, true]>;
|
|
41
|
+
//=> true
|
|
42
|
+
|
|
43
|
+
type B = OrAll<[never, never, false]>;
|
|
44
|
+
//=> false
|
|
45
|
+
|
|
46
|
+
type C = OrAll<[never, never, never]>;
|
|
47
|
+
//=> false
|
|
48
|
+
|
|
49
|
+
type D = OrAll<[never, never, boolean]>;
|
|
50
|
+
//=> boolean
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Note: If `any` is passed as an element, it is treated as `boolean` and the result is computed accordingly.
|
|
54
|
+
|
|
55
|
+
@example
|
|
56
|
+
```
|
|
57
|
+
import type {OrAll} from 'type-fest';
|
|
58
|
+
|
|
59
|
+
type A = OrAll<[false, any]>;
|
|
60
|
+
//=> boolean
|
|
61
|
+
|
|
62
|
+
type B = OrAll<[true, any]>;
|
|
63
|
+
//=> true
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Note: `OrAll<[]>` evaluates to `false` because there are no `true` elements in an empty tuple. See [Wikipedia: Clause (logic) > Empty clauses](https://en.wikipedia.org/wiki/Clause_(logic)#Empty_clauses:~:text=The%20truth%20evaluation%20of%20an%20empty%20disjunctive%20clause%20is%20always%20false.).
|
|
67
|
+
|
|
68
|
+
@see {@link Or}
|
|
69
|
+
@see {@link AndAll}
|
|
70
|
+
*/
|
|
71
|
+
export type OrAll<T extends readonly boolean[]> = SomeExtend<T, true>;
|
|
72
|
+
|
|
73
|
+
export {};
|
package/source/or.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {IsNever} from './is-never.d.ts';
|
|
1
|
+
import type {OrAll} from './or-all.d.ts';
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
4
|
Returns a boolean for whether either of two given types is true.
|
|
@@ -74,16 +73,10 @@ type G = Or<never, never>;
|
|
|
74
73
|
//=> false
|
|
75
74
|
```
|
|
76
75
|
|
|
76
|
+
@see {@link OrAll}
|
|
77
77
|
@see {@link And}
|
|
78
78
|
@see {@link Xor}
|
|
79
79
|
*/
|
|
80
|
-
export type Or<A extends boolean, B extends boolean> =
|
|
81
|
-
_Or<If<IsNever<A>, false, A>, If<IsNever<B>, false, B>>; // `never` is treated as `false`
|
|
82
|
-
|
|
83
|
-
export type _Or<A extends boolean, B extends boolean> = A extends true
|
|
84
|
-
? true
|
|
85
|
-
: B extends true
|
|
86
|
-
? true
|
|
87
|
-
: false;
|
|
80
|
+
export type Or<A extends boolean, B extends boolean> = OrAll<[A, B]>;
|
|
88
81
|
|
|
89
82
|
export {};
|
package/source/package-json.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type {LiteralUnion} from './literal-union.d.ts';
|
|
2
1
|
import type {JsonObject, JsonValue} from './json-value.d.ts';
|
|
2
|
+
import type {LiteralUnion} from './literal-union.d.ts';
|
|
3
3
|
|
|
4
4
|
export namespace PackageJson {
|
|
5
5
|
/**
|
|
@@ -526,7 +526,7 @@ export namespace PackageJson {
|
|
|
526
526
|
Engines that this package runs on.
|
|
527
527
|
*/
|
|
528
528
|
engines?: {
|
|
529
|
-
[EngineName in 'npm' | 'node'
|
|
529
|
+
[EngineName in LiteralUnion<'npm' | 'node', string>]?: string;
|
|
530
530
|
};
|
|
531
531
|
|
|
532
532
|
/**
|
package/source/paths.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {NonRecursiveType, ToString, IsNumberLike, ApplyDefaultOptions, MapsSetsOrArrays} from './internal/index.d.ts';
|
|
2
2
|
import type {IsAny} from './is-any.d.ts';
|
|
3
3
|
import type {UnknownArray} from './unknown-array.d.ts';
|
|
4
4
|
import type {GreaterThan} from './greater-than.d.ts';
|
|
@@ -192,67 +192,50 @@ open('listB.1'); // TypeError. Because listB only has one element.
|
|
|
192
192
|
export type Paths<T, Options extends PathsOptions = {}> = _Paths<T, ApplyDefaultOptions<PathsOptions, DefaultPathsOptions, Options>>;
|
|
193
193
|
|
|
194
194
|
type _Paths<T, Options extends Required<PathsOptions>, CurrentDepth extends number = 0> =
|
|
195
|
-
T extends NonRecursiveType |
|
|
195
|
+
T extends NonRecursiveType | Exclude<MapsSetsOrArrays, UnknownArray>
|
|
196
196
|
? never
|
|
197
197
|
: IsAny<T> extends true
|
|
198
198
|
? never
|
|
199
|
-
: T extends
|
|
200
|
-
?
|
|
201
|
-
|
|
202
|
-
? InternalPaths<StaticPartOfArray<T>, Options, CurrentDepth> | InternalPaths<Array<VariablePartOfArray<T>[number]>, Options, CurrentDepth>
|
|
203
|
-
: InternalPaths<T, Options, CurrentDepth>
|
|
204
|
-
: T extends object
|
|
205
|
-
? InternalPaths<T, Options, CurrentDepth>
|
|
206
|
-
: never;
|
|
199
|
+
: T extends object
|
|
200
|
+
? InternalPaths<Required<T>, Options, CurrentDepth>
|
|
201
|
+
: never;
|
|
207
202
|
|
|
208
203
|
type InternalPaths<T, Options extends Required<PathsOptions>, CurrentDepth extends number> =
|
|
209
|
-
|
|
210
|
-
?
|
|
211
|
-
|
|
212
|
-
?
|
|
213
|
-
:
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
? CurrentDepth extends Options['depth']
|
|
243
|
-
? _TransformedKey
|
|
244
|
-
: never
|
|
245
|
-
: never)
|
|
246
|
-
| (
|
|
247
|
-
// Recursively generate paths for the current key
|
|
248
|
-
GreaterThan<MaxDepth, CurrentDepth> extends true // Limit the depth to prevent infinite recursion
|
|
249
|
-
? `${TranformedKey}${_Paths<T[Key], Options, Sum<CurrentDepth, 1>> & (string | number)}`
|
|
250
|
-
: never
|
|
251
|
-
)
|
|
252
|
-
: never
|
|
253
|
-
: never
|
|
254
|
-
}[keyof T & (T extends UnknownArray ? number : unknown)]
|
|
204
|
+
{[Key in keyof T]: Key extends string | number // Limit `Key` to `string | number`
|
|
205
|
+
? (
|
|
206
|
+
And<Options['bracketNotation'], IsNumberLike<Key>> extends true
|
|
207
|
+
? `[${Key}]`
|
|
208
|
+
: CurrentDepth extends 0
|
|
209
|
+
// Return both `Key` and `ToString<Key>` because for number keys, like `1`, both `1` and `'1'` are valid keys.
|
|
210
|
+
? Key | ToString<Key>
|
|
211
|
+
: `.${(Key | ToString<Key>)}`
|
|
212
|
+
) extends infer TransformedKey extends string | number
|
|
213
|
+
? ((Options['leavesOnly'] extends true
|
|
214
|
+
? Options['maxRecursionDepth'] extends CurrentDepth
|
|
215
|
+
? TransformedKey
|
|
216
|
+
: IsNever<T[Key]> extends true
|
|
217
|
+
? TransformedKey
|
|
218
|
+
: T[Key] extends infer Value // For distributing `T[Key]`
|
|
219
|
+
? (Value extends readonly [] | NonRecursiveType | Exclude<MapsSetsOrArrays, UnknownArray>
|
|
220
|
+
? TransformedKey
|
|
221
|
+
: IsNever<keyof Value> extends true // Check for empty object & `unknown`, because `keyof unknown` is `never`.
|
|
222
|
+
? TransformedKey
|
|
223
|
+
: never)
|
|
224
|
+
: never // Should never happen
|
|
225
|
+
: TransformedKey
|
|
226
|
+
) extends infer _TransformedKey
|
|
227
|
+
// If `depth` is provided, the condition becomes truthy only when it matches `CurrentDepth`.
|
|
228
|
+
// Otherwise, since `depth` defaults to `number`, the condition is always truthy, returning paths at all depths.
|
|
229
|
+
? CurrentDepth extends Options['depth']
|
|
230
|
+
? _TransformedKey
|
|
231
|
+
: never
|
|
232
|
+
: never)
|
|
233
|
+
// Recursively generate paths for the current key
|
|
234
|
+
| (GreaterThan<Options['maxRecursionDepth'], CurrentDepth> extends true // Limit the depth to prevent infinite recursion
|
|
235
|
+
? `${TransformedKey}${_Paths<T[Key], Options, Sum<CurrentDepth, 1>> & (string | number)}`
|
|
236
|
+
: never)
|
|
255
237
|
: never
|
|
256
|
-
: never
|
|
238
|
+
: never
|
|
239
|
+
}[keyof T & (T extends UnknownArray ? number : unknown)];
|
|
257
240
|
|
|
258
241
|
export {};
|
package/source/pick-deep.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type {Paths} from './paths.d.ts';
|
|
|
5
5
|
import type {Simplify} from './simplify.d.ts';
|
|
6
6
|
import type {UnionToIntersection} from './union-to-intersection.d.ts';
|
|
7
7
|
import type {UnknownArray} from './unknown-array.d.ts';
|
|
8
|
+
import type {SimplifyDeep} from './simplify-deep.d.ts';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
Pick properties from a deeply-nested object.
|
|
@@ -36,24 +37,15 @@ type Configuration = {
|
|
|
36
37
|
};
|
|
37
38
|
|
|
38
39
|
type NameConfig = PickDeep<Configuration, 'userConfig.name'>;
|
|
39
|
-
|
|
40
|
-
// userConfig: {
|
|
41
|
-
// name: string;
|
|
42
|
-
// }
|
|
43
|
-
// };
|
|
40
|
+
//=> {userConfig: {name: string}}
|
|
44
41
|
|
|
45
42
|
// Supports optional properties
|
|
46
43
|
type User = PickDeep<PartialDeep<Configuration>, 'userConfig.name' | 'userConfig.age'>;
|
|
47
|
-
|
|
48
|
-
// userConfig?: {
|
|
49
|
-
// name?: string;
|
|
50
|
-
// age?: number;
|
|
51
|
-
// };
|
|
52
|
-
// };
|
|
44
|
+
//=> {userConfig?: {name?: string; age?: number}}
|
|
53
45
|
|
|
54
46
|
// Supports array
|
|
55
47
|
type AddressConfig = PickDeep<Configuration, 'userConfig.address.0'>;
|
|
56
|
-
|
|
48
|
+
//=> {
|
|
57
49
|
// userConfig: {
|
|
58
50
|
// address: [{
|
|
59
51
|
// city1: string;
|
|
@@ -64,14 +56,7 @@ type AddressConfig = PickDeep<Configuration, 'userConfig.address.0'>;
|
|
|
64
56
|
|
|
65
57
|
// Supports recurse into array
|
|
66
58
|
type Street = PickDeep<Configuration, 'userConfig.address.1.street2'>;
|
|
67
|
-
|
|
68
|
-
// userConfig: {
|
|
69
|
-
// address: [
|
|
70
|
-
// unknown,
|
|
71
|
-
// {street2: string}
|
|
72
|
-
// ];
|
|
73
|
-
// };
|
|
74
|
-
// }
|
|
59
|
+
//=> {userConfig: {address: [unknown, {street2: string}]}}
|
|
75
60
|
```
|
|
76
61
|
|
|
77
62
|
@category Object
|
|
@@ -86,7 +71,7 @@ export type PickDeep<T, PathUnion extends Paths<T>> =
|
|
|
86
71
|
}[PathUnion]
|
|
87
72
|
>
|
|
88
73
|
: T extends object
|
|
89
|
-
?
|
|
74
|
+
? SimplifyDeep<UnionToIntersection<{
|
|
90
75
|
[P in PathUnion]: InternalPickDeep<T, P>;
|
|
91
76
|
}[PathUnion]>>
|
|
92
77
|
: never;
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
package/source/set-optional.d.ts
CHANGED
|
@@ -18,11 +18,7 @@ type Foo = {
|
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
type SomeOptional = SetOptional<Foo, 'b' | 'c'>;
|
|
21
|
-
|
|
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
|
|
@@ -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
|
|
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: `
|
|
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]
|
package/source/set-readonly.d.ts
CHANGED
|
@@ -18,11 +18,7 @@ type Foo = {
|
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
type SomeReadonly = SetReadonly<Foo, 'b' | 'c'>;
|
|
21
|
-
|
|
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
|
package/source/set-required.d.ts
CHANGED
|
@@ -21,11 +21,7 @@ type Foo = {
|
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
type SomeRequired = SetRequired<Foo, 'b' | 'c'>;
|
|
24
|
-
|
|
25
|
-
// a?: number;
|
|
26
|
-
// b: string; // Was already required and still is.
|
|
27
|
-
// c: boolean; // Is now required.
|
|
28
|
-
// }
|
|
24
|
+
//=> {a?: number; b: string; c: boolean}
|
|
29
25
|
|
|
30
26
|
// Set specific indices in an array to be required.
|
|
31
27
|
type ArrayExample = SetRequired<[number?, number?, number?], 0 | 1>;
|
|
@@ -89,7 +89,7 @@ function displayPetInfoWithSharedUnionFieldsDeep(petInfo: SharedUnionFieldsDeep<
|
|
|
89
89
|
export type SharedUnionFieldsDeep<Union, Options extends SharedUnionFieldsDeepOptions = {}> =
|
|
90
90
|
ApplyDefaultOptions<SharedUnionFieldsDeepOptions, DefaultSharedUnionFieldsDeepOptions, Options> extends infer OptionsWithDefaults extends Required<SharedUnionFieldsDeepOptions>
|
|
91
91
|
// `Union extends` will convert `Union`
|
|
92
|
-
// to a [distributive
|
|
92
|
+
// to a [distributive conditional type](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#distributive-conditional-types).
|
|
93
93
|
// But this is not what we want, so we need to wrap `Union` with `[]` to prevent it.
|
|
94
94
|
? [Union] extends [NonRecursiveType | ReadonlyMap<unknown, unknown> | ReadonlySet<unknown>]
|
|
95
95
|
? Union
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import type {CollapseRestElement} from './internal/array.d.ts';
|
|
2
|
+
import type {ApplyDefaultOptions} from './internal/object.d.ts';
|
|
3
|
+
import type {IfNotAnyOrNever, Not} from './internal/type.d.ts';
|
|
4
|
+
import type {IsAny} from './is-any.d.ts';
|
|
5
|
+
import type {IsNever} from './is-never.d.ts';
|
|
6
|
+
import type {Or} from './or.d.ts';
|
|
7
|
+
import type {UnknownArray} from './unknown-array.d.ts';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
@see {@link SomeExtend}
|
|
11
|
+
*/
|
|
12
|
+
export type SomeExtendOptions = {
|
|
13
|
+
/**
|
|
14
|
+
Consider `never` elements to match the target type only if the target type itself is `never` (or `any`).
|
|
15
|
+
|
|
16
|
+
- When set to `true` (default), `never` is _not_ treated as a bottom type, instead, it is treated as a type that matches only itself (or `any`).
|
|
17
|
+
- When set to `false`, `never` is treated as a bottom type, and behaves as it normally would.
|
|
18
|
+
|
|
19
|
+
@default true
|
|
20
|
+
|
|
21
|
+
@example
|
|
22
|
+
```
|
|
23
|
+
import type {SomeExtend} from 'type-fest';
|
|
24
|
+
|
|
25
|
+
type A = SomeExtend<[1, 2, never], string, {strictNever: true}>;
|
|
26
|
+
//=> false
|
|
27
|
+
|
|
28
|
+
type B = SomeExtend<[1, 2, never], string, {strictNever: false}>;
|
|
29
|
+
//=> true
|
|
30
|
+
|
|
31
|
+
type C = SomeExtend<[1, never], never, {strictNever: true}>;
|
|
32
|
+
//=> true
|
|
33
|
+
|
|
34
|
+
type D = SomeExtend<[1, never], never, {strictNever: false}>;
|
|
35
|
+
//=> true
|
|
36
|
+
|
|
37
|
+
type E = SomeExtend<[never], any, {strictNever: true}>;
|
|
38
|
+
//=> true
|
|
39
|
+
|
|
40
|
+
type F = SomeExtend<[never], any, {strictNever: false}>;
|
|
41
|
+
//=> true
|
|
42
|
+
```
|
|
43
|
+
*/
|
|
44
|
+
strictNever?: boolean;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
type DefaultSomeExtendOptions = {
|
|
48
|
+
strictNever: true;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
Returns a boolean for whether some element in an array type extends another type.
|
|
53
|
+
|
|
54
|
+
@example
|
|
55
|
+
```
|
|
56
|
+
import type {SomeExtend} from 'type-fest';
|
|
57
|
+
|
|
58
|
+
type A = SomeExtend<['1', '2', 3], number>;
|
|
59
|
+
//=> true
|
|
60
|
+
|
|
61
|
+
type B = SomeExtend<[1, 2, 3], string>;
|
|
62
|
+
//=> false
|
|
63
|
+
|
|
64
|
+
type C = SomeExtend<[string, number | string], number>;
|
|
65
|
+
//=> boolean
|
|
66
|
+
|
|
67
|
+
type D = SomeExtend<[true, boolean, true], false>;
|
|
68
|
+
//=> boolean
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Note: Behaviour of optional elements depend on the `exactOptionalPropertyTypes` compiler option. When the option is disabled, the target type must include `undefined` for a successful match.
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
// @exactOptionalPropertyTypes: true
|
|
75
|
+
import type {SomeExtend} from 'type-fest';
|
|
76
|
+
|
|
77
|
+
type A = SomeExtend<[1?, 2?, '3'?], string>;
|
|
78
|
+
//=> true
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
// @exactOptionalPropertyTypes: false
|
|
83
|
+
import type {SomeExtend} from 'type-fest';
|
|
84
|
+
|
|
85
|
+
type A = SomeExtend<[1?, 2?, '3'?], string>;
|
|
86
|
+
//=> boolean
|
|
87
|
+
|
|
88
|
+
type B = SomeExtend<[1?, 2?, '3'?], string | undefined>;
|
|
89
|
+
//=> true
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
@see {@link SomeExtendOptions}
|
|
93
|
+
|
|
94
|
+
@category Utilities
|
|
95
|
+
@category Array
|
|
96
|
+
*/
|
|
97
|
+
export type SomeExtend<TArray extends UnknownArray, Type, Options extends SomeExtendOptions = {}> =
|
|
98
|
+
_SomeExtend<CollapseRestElement<TArray>, Type, ApplyDefaultOptions<SomeExtendOptions, DefaultSomeExtendOptions, Options>>;
|
|
99
|
+
|
|
100
|
+
type _SomeExtend<TArray extends UnknownArray, Type, Options extends Required<SomeExtendOptions>> = IfNotAnyOrNever<TArray,
|
|
101
|
+
TArray extends readonly [infer First, ...infer Rest]
|
|
102
|
+
? IsNever<First> extends true
|
|
103
|
+
? Or<Or<IsNever<Type>, IsAny<Type>>, Not<Options['strictNever']>> extends true
|
|
104
|
+
// If target `Type` is also `never`, or is `any`, or `strictNever` is disabled, return `true`.
|
|
105
|
+
? true
|
|
106
|
+
: _SomeExtend<Rest, Type, Options>
|
|
107
|
+
: First extends Type
|
|
108
|
+
? true
|
|
109
|
+
: _SomeExtend<Rest, Type, Options>
|
|
110
|
+
: false,
|
|
111
|
+
false, false>;
|
|
112
|
+
|
|
113
|
+
export {};
|
package/source/spread.d.ts
CHANGED
|
@@ -41,11 +41,7 @@ const bar = {c: false};
|
|
|
41
41
|
const fooBar = {...foo, ...bar};
|
|
42
42
|
|
|
43
43
|
type FooBar = Spread<Foo, Bar>;
|
|
44
|
-
|
|
45
|
-
// a: number;
|
|
46
|
-
// b?: string | number | undefined;
|
|
47
|
-
// c: boolean;
|
|
48
|
-
// }
|
|
44
|
+
//=> {a: number; b?: string | number; c: boolean}
|
|
49
45
|
|
|
50
46
|
declare function baz(argument: FooBar): void;
|
|
51
47
|
|
package/source/tagged.d.ts
CHANGED
|
@@ -121,7 +121,7 @@ const moneyByAccountType: Record<UnwrapTagged<AccountType>, number> = {
|
|
|
121
121
|
// Without UnwrapTagged, the following expression would throw a type error.
|
|
122
122
|
const money = moneyByAccountType.SAVINGS; // TS error: Property 'SAVINGS' does not exist
|
|
123
123
|
|
|
124
|
-
// Attempting to pass
|
|
124
|
+
// Attempting to pass a non-Tagged type to UnwrapTagged will raise a type error.
|
|
125
125
|
// @ts-expect-error
|
|
126
126
|
type WontWork = UnwrapTagged<string>;
|
|
127
127
|
```
|
|
@@ -239,7 +239,7 @@ const moneyByAccountType: Record<UnwrapOpaque<AccountType>, number> = {
|
|
|
239
239
|
// Without UnwrapOpaque, the following expression would throw a type error.
|
|
240
240
|
const money = moneyByAccountType.SAVINGS; // TS error: Property 'SAVINGS' does not exist
|
|
241
241
|
|
|
242
|
-
// Attempting to pass
|
|
242
|
+
// Attempting to pass a non-Opaque type to UnwrapOpaque will raise a type error.
|
|
243
243
|
// @ts-expect-error
|
|
244
244
|
type WontWork = UnwrapOpaque<string>;
|
|
245
245
|
|