type-fest 4.31.0 → 4.32.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 +2 -0
- package/package.json +1 -1
- package/readme.md +3 -0
- package/source/internal/array.d.ts +34 -1
- package/source/is-tuple.d.ts +78 -0
- package/source/partial-deep.d.ts +38 -10
- package/source/set-required-deep.d.ts +46 -0
- package/source/set-required.d.ts +37 -8
package/index.d.ts
CHANGED
|
@@ -42,6 +42,7 @@ export type {InvariantOf} from './source/invariant-of';
|
|
|
42
42
|
export type {SetOptional} from './source/set-optional';
|
|
43
43
|
export type {SetReadonly} from './source/set-readonly';
|
|
44
44
|
export type {SetRequired} from './source/set-required';
|
|
45
|
+
export type {SetRequiredDeep} from './source/set-required-deep';
|
|
45
46
|
export type {SetNonNullable} from './source/set-non-nullable';
|
|
46
47
|
export type {ValueOf} from './source/value-of';
|
|
47
48
|
export type {AsyncReturnType} from './source/async-return-type';
|
|
@@ -121,6 +122,7 @@ export type {IsNever} from './source/is-never';
|
|
|
121
122
|
export type {IfNever} from './source/if-never';
|
|
122
123
|
export type {IsUnknown} from './source/is-unknown';
|
|
123
124
|
export type {IfUnknown} from './source/if-unknown';
|
|
125
|
+
export type {IsTuple} from './source/is-tuple';
|
|
124
126
|
export type {ArrayIndices} from './source/array-indices';
|
|
125
127
|
export type {ArrayValues} from './source/array-values';
|
|
126
128
|
export type {ArraySlice} from './source/array-slice';
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -159,6 +159,7 @@ Click the type names for complete docs.
|
|
|
159
159
|
- [`SetOptional`](source/set-optional.d.ts) - Create a type that makes the given keys optional.
|
|
160
160
|
- [`SetReadonly`](source/set-readonly.d.ts) - Create a type that makes the given keys readonly.
|
|
161
161
|
- [`SetRequired`](source/set-required.d.ts) - Create a type that makes the given keys required.
|
|
162
|
+
- [`SetRequiredDeep`](source/set-required-deep.d.ts) - Like `SetRequired` except it selects the keys deeply.
|
|
162
163
|
- [`SetNonNullable`](source/set-non-nullable.d.ts) - Create a type that makes the given keys non-nullable.
|
|
163
164
|
- [`ValueOf`](source/value-of.d.ts) - Create a union of the given object's values, and optionally specify which keys to get the values from.
|
|
164
165
|
- [`ConditionalKeys`](source/conditional-keys.d.ts) - Extract keys from a shape where values extend the given `Condition` type.
|
|
@@ -247,6 +248,7 @@ type ShouldBeNever = IfAny<'not any', 'not never', 'never'>;
|
|
|
247
248
|
- [`IsUnknown`](source/is-unknown.d.ts) - Returns a boolean for whether the given type is `unknown`. (Conditional version: [`IfUnknown`](source/if-unknown.d.ts))
|
|
248
249
|
- [`IsEmptyObject`](source/empty-object.d.ts) - Returns a boolean for whether the type is strictly equal to an empty plain object, the `{}` value. (Conditional version: [`IfEmptyObject`](source/if-empty-object.d.ts))
|
|
249
250
|
- [`IsNull`](source/is-null.d.ts) - Returns a boolean for whether the given type is `null`. (Conditional version: [`IfNull`](source/if-null.d.ts))
|
|
251
|
+
- [`IsTuple`](source/is-tuple.d.ts) - Returns a boolean for whether the given array is a tuple.
|
|
250
252
|
|
|
251
253
|
### JSON
|
|
252
254
|
|
|
@@ -1049,6 +1051,7 @@ You can find some examples in the [TypeScript docs](https://www.typescriptlang.o
|
|
|
1049
1051
|
|
|
1050
1052
|
- [Sindre Sorhus](https://github.com/sindresorhus)
|
|
1051
1053
|
- [Haozheng Li](https://github.com/Emiyaaaaa)
|
|
1054
|
+
- [Som Shekhar Mukherjee](https://github.com/som-sm)
|
|
1052
1055
|
- [Jarek Radosz](https://github.com/CvX)
|
|
1053
1056
|
- [Dimitri Benin](https://github.com/BendingBender)
|
|
1054
1057
|
- [Pelle Wessman](https://github.com/voxpelli)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type {IfNever} from '../if-never';
|
|
1
2
|
import type {UnknownArray} from '../unknown-array';
|
|
2
3
|
|
|
3
4
|
/**
|
|
@@ -90,4 +91,36 @@ T extends readonly [...infer U] ?
|
|
|
90
91
|
/**
|
|
91
92
|
Returns whether the given array `T` is readonly.
|
|
92
93
|
*/
|
|
93
|
-
export type IsArrayReadonly<T extends UnknownArray> = T extends unknown[] ? false : true
|
|
94
|
+
export type IsArrayReadonly<T extends UnknownArray> = IfNever<T, false, T extends unknown[] ? false : true>;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
An if-else-like type that resolves depending on whether the given array is readonly.
|
|
98
|
+
|
|
99
|
+
@see {@link IsArrayReadonly}
|
|
100
|
+
|
|
101
|
+
@example
|
|
102
|
+
```
|
|
103
|
+
import type {ArrayTail} from 'type-fest';
|
|
104
|
+
|
|
105
|
+
type ReadonlyPreservingArrayTail<TArray extends readonly unknown[]> =
|
|
106
|
+
ArrayTail<TArray> extends infer Tail
|
|
107
|
+
? IfArrayReadonly<TArray, Readonly<Tail>, Tail>
|
|
108
|
+
: never;
|
|
109
|
+
|
|
110
|
+
type ReadonlyTail = ReadonlyPreservingArrayTail<readonly [string, number, boolean]>;
|
|
111
|
+
//=> readonly [number, boolean]
|
|
112
|
+
|
|
113
|
+
type NonReadonlyTail = ReadonlyPreservingArrayTail<[string, number, boolean]>;
|
|
114
|
+
//=> [number, boolean]
|
|
115
|
+
|
|
116
|
+
type ShouldBeTrue = IfArrayReadonly<readonly unknown[]>;
|
|
117
|
+
//=> true
|
|
118
|
+
|
|
119
|
+
type ShouldBeBar = IfArrayReadonly<unknown[], 'foo', 'bar'>;
|
|
120
|
+
//=> 'bar'
|
|
121
|
+
```
|
|
122
|
+
*/
|
|
123
|
+
export type IfArrayReadonly<T extends UnknownArray, TypeIfArrayReadonly = true, TypeIfNotArrayReadonly = false> =
|
|
124
|
+
IsArrayReadonly<T> extends infer Result
|
|
125
|
+
? Result extends true ? TypeIfArrayReadonly : TypeIfNotArrayReadonly
|
|
126
|
+
: never; // Should never happen
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type {IfAny} from './if-any';
|
|
2
|
+
import type {IfNever} from './if-never';
|
|
3
|
+
import type {UnknownArray} from './unknown-array';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
@see {@link IsTuple}
|
|
7
|
+
*/
|
|
8
|
+
export type IsTupleOptions = {
|
|
9
|
+
/**
|
|
10
|
+
Consider only fixed length arrays as tuples.
|
|
11
|
+
|
|
12
|
+
- When set to `true` (default), arrays with rest elements (e.g., `[1, ...number[]]`) are _not_ considered as tuples.
|
|
13
|
+
- When set to `false`, arrays with at least one non-rest element (e.g., `[1, ...number[]]`) are considered as tuples.
|
|
14
|
+
|
|
15
|
+
@default true
|
|
16
|
+
|
|
17
|
+
@example
|
|
18
|
+
```ts
|
|
19
|
+
import type {IsTuple} from 'type-fest';
|
|
20
|
+
|
|
21
|
+
type Example1 = IsTuple<[number, ...number[]], {fixedLengthOnly: true}>;
|
|
22
|
+
//=> false
|
|
23
|
+
|
|
24
|
+
type Example2 = IsTuple<[number, ...number[]], {fixedLengthOnly: false}>;
|
|
25
|
+
//=> true
|
|
26
|
+
```
|
|
27
|
+
*/
|
|
28
|
+
fixedLengthOnly?: boolean;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
Returns a boolean for whether the given array is a tuple.
|
|
33
|
+
|
|
34
|
+
Use-case:
|
|
35
|
+
- If you want to make a conditional branch based on the result of whether an array is a tuple or not.
|
|
36
|
+
|
|
37
|
+
Note: `IsTuple` returns `boolean` when instantiated with a union of tuple and non-tuple (e.g., `IsTuple<[1, 2] | number[]>`).
|
|
38
|
+
|
|
39
|
+
@example
|
|
40
|
+
```ts
|
|
41
|
+
import type {IsTuple} from 'type-fest';
|
|
42
|
+
|
|
43
|
+
type Tuple = IsTuple<[1, 2, 3]>;
|
|
44
|
+
//=> true
|
|
45
|
+
|
|
46
|
+
type NotTuple = IsTuple<number[]>;
|
|
47
|
+
//=> false
|
|
48
|
+
|
|
49
|
+
type TupleWithOptionalItems = IsTuple<[1?, 2?]>;
|
|
50
|
+
//=> true
|
|
51
|
+
|
|
52
|
+
type RestItemsNotAllowed = IsTuple<[1, 2, ...number[]]>;
|
|
53
|
+
//=> false
|
|
54
|
+
|
|
55
|
+
type RestItemsAllowed = IsTuple<[1, 2, ...number[]], {fixedLengthOnly: false}>;
|
|
56
|
+
//=> true
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
@see {@link IsTupleOptions}
|
|
60
|
+
|
|
61
|
+
@category Type Guard
|
|
62
|
+
@category Utilities
|
|
63
|
+
*/
|
|
64
|
+
export type IsTuple<
|
|
65
|
+
TArray extends UnknownArray,
|
|
66
|
+
Options extends IsTupleOptions = {fixedLengthOnly: true},
|
|
67
|
+
> =
|
|
68
|
+
IfAny<TArray, boolean, IfNever<TArray, false,
|
|
69
|
+
TArray extends unknown // For distributing `TArray`
|
|
70
|
+
? number extends TArray['length']
|
|
71
|
+
? Options['fixedLengthOnly'] extends false
|
|
72
|
+
? IfNever<keyof TArray & `${number}`,
|
|
73
|
+
TArray extends readonly [...any, any] ? true : false, // To handle cases where a non-rest element follows a rest element, e.g., `[...number[], number]`
|
|
74
|
+
true>
|
|
75
|
+
: false
|
|
76
|
+
: true
|
|
77
|
+
: false
|
|
78
|
+
>>;
|
package/source/partial-deep.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type {BuiltIns} from './internal';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
@see PartialDeep
|
|
4
|
+
@see {@link PartialDeep}
|
|
5
5
|
*/
|
|
6
6
|
export type PartialDeepOptions = {
|
|
7
7
|
/**
|
|
@@ -10,6 +10,32 @@ export type PartialDeepOptions = {
|
|
|
10
10
|
@default false
|
|
11
11
|
*/
|
|
12
12
|
readonly recurseIntoArrays?: boolean;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
Allows `undefined` values in non-tuple arrays.
|
|
16
|
+
|
|
17
|
+
- When set to `true`, elements of non-tuple arrays can be `undefined`.
|
|
18
|
+
- When set to `false`, only explicitly defined elements are allowed in non-tuple arrays, ensuring stricter type checking.
|
|
19
|
+
|
|
20
|
+
@default true
|
|
21
|
+
|
|
22
|
+
@example
|
|
23
|
+
You can prevent `undefined` values in non-tuple arrays by passing `{recurseIntoArrays: true; allowUndefinedInNonTupleArrays: false}` as the second type argument:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
import type {PartialDeep} from 'type-fest';
|
|
27
|
+
|
|
28
|
+
type Settings = {
|
|
29
|
+
languages: string[];
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
declare const partialSettings: PartialDeep<Settings, {recurseIntoArrays: true; allowUndefinedInNonTupleArrays: false}>;
|
|
33
|
+
|
|
34
|
+
partialSettings.languages = [undefined]; // Error
|
|
35
|
+
partialSettings.languages = []; // Ok
|
|
36
|
+
```
|
|
37
|
+
*/
|
|
38
|
+
readonly allowUndefinedInNonTupleArrays?: boolean;
|
|
13
39
|
};
|
|
14
40
|
|
|
15
41
|
/**
|
|
@@ -25,12 +51,12 @@ import type {PartialDeep} from 'type-fest';
|
|
|
25
51
|
|
|
26
52
|
const settings: Settings = {
|
|
27
53
|
textEditor: {
|
|
28
|
-
fontSize: 14
|
|
29
|
-
fontColor: '#000000'
|
|
30
|
-
fontWeight: 400
|
|
31
|
-
}
|
|
32
|
-
autocomplete: false
|
|
33
|
-
autosave: true
|
|
54
|
+
fontSize: 14,
|
|
55
|
+
fontColor: '#000000',
|
|
56
|
+
fontWeight: 400
|
|
57
|
+
},
|
|
58
|
+
autocomplete: false,
|
|
59
|
+
autosave: true
|
|
34
60
|
};
|
|
35
61
|
|
|
36
62
|
const applySavedSettings = (savedSettings: PartialDeep<Settings>) => {
|
|
@@ -45,7 +71,7 @@ By default, this does not affect elements in array and tuple types. You can chan
|
|
|
45
71
|
```
|
|
46
72
|
import type {PartialDeep} from 'type-fest';
|
|
47
73
|
|
|
48
|
-
|
|
74
|
+
type Settings = {
|
|
49
75
|
languages: string[];
|
|
50
76
|
}
|
|
51
77
|
|
|
@@ -54,6 +80,8 @@ const partialSettings: PartialDeep<Settings, {recurseIntoArrays: true}> = {
|
|
|
54
80
|
};
|
|
55
81
|
```
|
|
56
82
|
|
|
83
|
+
@see {@link PartialDeepOptions}
|
|
84
|
+
|
|
57
85
|
@category Object
|
|
58
86
|
@category Array
|
|
59
87
|
@category Set
|
|
@@ -74,8 +102,8 @@ export type PartialDeep<T, Options extends PartialDeepOptions = {}> = T extends
|
|
|
74
102
|
? Options['recurseIntoArrays'] extends true
|
|
75
103
|
? ItemType[] extends T // Test for arrays (non-tuples) specifically
|
|
76
104
|
? readonly ItemType[] extends T // Differentiate readonly and mutable arrays
|
|
77
|
-
? ReadonlyArray<PartialDeep<ItemType | undefined, Options>>
|
|
78
|
-
: Array<PartialDeep<ItemType | undefined, Options>>
|
|
105
|
+
? ReadonlyArray<PartialDeep<Options['allowUndefinedInNonTupleArrays'] extends false ? ItemType : ItemType | undefined, Options>>
|
|
106
|
+
: Array<PartialDeep<Options['allowUndefinedInNonTupleArrays'] extends false ? ItemType : ItemType | undefined, Options>>
|
|
79
107
|
: PartialObjectDeep<T, Options> // Tuples behave properly
|
|
80
108
|
: T // If they don't opt into array testing, just use the original type
|
|
81
109
|
: PartialObjectDeep<T, Options>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type {NonRecursiveType, StringToNumber} from './internal';
|
|
2
|
+
import type {Paths} from './paths';
|
|
3
|
+
import type {SimplifyDeep} from './simplify-deep';
|
|
4
|
+
import type {UnknownArray} from './unknown-array';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
Create a type that makes the given keys required. You can specify deeply nested key paths. The remaining keys are kept as is.
|
|
8
|
+
|
|
9
|
+
Use-case: Selectively make nested properties required in complex types like models.
|
|
10
|
+
|
|
11
|
+
@example
|
|
12
|
+
```
|
|
13
|
+
import type {SetRequiredDeep} from 'type-fest';
|
|
14
|
+
|
|
15
|
+
type Foo = {
|
|
16
|
+
a?: number;
|
|
17
|
+
b?: string;
|
|
18
|
+
c?: {
|
|
19
|
+
d?: number
|
|
20
|
+
}[]
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
type SomeRequiredDeep = SetRequiredDeep<Foo, 'a' | `c.${number}.d`>;
|
|
24
|
+
// type SomeRequiredDeep = {
|
|
25
|
+
// a: number; // Is now required
|
|
26
|
+
// b?: string;
|
|
27
|
+
// c: {
|
|
28
|
+
// d: number // Is now required
|
|
29
|
+
// }[]
|
|
30
|
+
// }
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
@category Object
|
|
34
|
+
*/
|
|
35
|
+
export type SetRequiredDeep<BaseType, KeyPaths extends Paths<BaseType>> =
|
|
36
|
+
BaseType extends NonRecursiveType
|
|
37
|
+
? BaseType
|
|
38
|
+
: SimplifyDeep<(
|
|
39
|
+
BaseType extends UnknownArray
|
|
40
|
+
? {}
|
|
41
|
+
: {[K in keyof BaseType as K extends (KeyPaths | StringToNumber<KeyPaths & string>) ? K : never]-?: BaseType[K]}
|
|
42
|
+
) & {
|
|
43
|
+
[K in keyof BaseType]: Extract<KeyPaths, `${K & (string | number)}.${string}`> extends never
|
|
44
|
+
? BaseType[K]
|
|
45
|
+
: SetRequiredDeep<BaseType[K], KeyPaths extends `${K & (string | number)}.${infer Rest extends Paths<BaseType[K]>}` ? Rest : never>
|
|
46
|
+
}>;
|
package/source/set-required.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type {Except} from './except';
|
|
2
|
-
import type {HomomorphicPick} from './internal';
|
|
2
|
+
import type {HomomorphicPick, IfArrayReadonly} from './internal';
|
|
3
3
|
import type {KeysOfUnion} from './keys-of-union';
|
|
4
|
+
import type {OptionalKeysOf} from './optional-keys-of';
|
|
4
5
|
import type {Simplify} from './simplify';
|
|
6
|
+
import type {UnknownArray} from './unknown-array';
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
9
|
Create a type that makes the given keys required. The remaining keys are kept as is. The sister of the `SetOptional` type.
|
|
@@ -24,19 +26,46 @@ type SomeRequired = SetRequired<Foo, 'b' | 'c'>;
|
|
|
24
26
|
// b: string; // Was already required and still is.
|
|
25
27
|
// c: boolean; // Is now required.
|
|
26
28
|
// }
|
|
29
|
+
|
|
30
|
+
// Set specific indices in an array to be required.
|
|
31
|
+
type ArrayExample = SetRequired<[number?, number?, number?], 0 | 1>;
|
|
32
|
+
//=> [number, number, number?]
|
|
27
33
|
```
|
|
28
34
|
|
|
29
35
|
@category Object
|
|
30
36
|
*/
|
|
31
37
|
export type SetRequired<BaseType, Keys extends keyof BaseType> =
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
38
|
+
BaseType extends UnknownArray
|
|
39
|
+
? SetArrayRequired<BaseType, Keys> extends infer ResultantArray
|
|
40
|
+
? IfArrayReadonly<BaseType, Readonly<ResultantArray>, ResultantArray>
|
|
41
|
+
: never
|
|
42
|
+
: Simplify<
|
|
37
43
|
// Pick just the keys that are optional from the base type.
|
|
38
44
|
Except<BaseType, Keys> &
|
|
39
45
|
// Pick the keys that should be required from the base type and make them required.
|
|
40
46
|
Required<HomomorphicPick<BaseType, Keys & KeysOfUnion<BaseType>>>
|
|
41
|
-
|
|
42
|
-
|
|
47
|
+
>;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
Remove the optional modifier from the specified keys in an array.
|
|
51
|
+
*/
|
|
52
|
+
type SetArrayRequired<
|
|
53
|
+
TArray extends UnknownArray,
|
|
54
|
+
Keys,
|
|
55
|
+
Counter extends any[] = [],
|
|
56
|
+
Accumulator extends UnknownArray = [],
|
|
57
|
+
> = TArray extends unknown // For distributing `TArray` when it's a union
|
|
58
|
+
? keyof TArray & `${number}` extends never
|
|
59
|
+
// Exit if `TArray` is empty (e.g., []), or
|
|
60
|
+
// `TArray` contains no non-rest elements preceding the rest element (e.g., `[...string[]]` or `[...string[], string]`).
|
|
61
|
+
? [...Accumulator, ...TArray]
|
|
62
|
+
: TArray extends readonly [(infer First)?, ...infer Rest]
|
|
63
|
+
? '0' extends OptionalKeysOf<TArray> // If the first element of `TArray` is optional
|
|
64
|
+
? `${Counter['length']}` extends `${Keys & (string | number)}` // If the current index needs to be required
|
|
65
|
+
? SetArrayRequired<Rest, Keys, [...Counter, any], [...Accumulator, First]>
|
|
66
|
+
// If the current element is optional, but it doesn't need to be required,
|
|
67
|
+
// then we can exit early, since no further elements can now be made required.
|
|
68
|
+
: [...Accumulator, ...TArray]
|
|
69
|
+
: SetArrayRequired<Rest, Keys, [...Counter, any], [...Accumulator, TArray[0]]>
|
|
70
|
+
: never // Should never happen, since `[(infer F)?, ...infer R]` is a top-type for arrays.
|
|
71
|
+
: never; // Should never happen
|