-
-
Notifications
You must be signed in to change notification settings - Fork 548
/
required-deep.d.ts
78 lines (69 loc) · 2.77 KB
/
required-deep.d.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import type {BuiltIns, HasMultipleCallSignatures} from './internal';
type ExcludeUndefined<T> = Exclude<T, undefined>;
/**
Create a type from another type with all keys and nested keys set to required.
Use-cases:
- Creating optional configuration interfaces where the underlying implementation still requires all options to be fully specified.
- Modeling the resulting type after a deep merge with a set of defaults.
@example
```
import type {RequiredDeep} from 'type-fest';
type Settings = {
textEditor?: {
fontSize?: number | undefined;
fontColor?: string | undefined;
fontWeight?: number | undefined;
}
autocomplete?: boolean | undefined;
autosave?: boolean | undefined;
};
type RequiredSettings = RequiredDeep<Settings>;
// type RequiredSettings = {
// textEditor: {
// fontSize: number;
// fontColor: string;
// fontWeight: number;
// }
// autocomplete: boolean;
// autosave: boolean;
// }
```
Note that types containing overloaded functions are not made deeply required due to a [TypeScript limitation](https://github.com/microsoft/TypeScript/issues/29732).
@category Utilities
@category Object
@category Array
@category Set
@category Map
*/
export type RequiredDeep<T, E extends ExcludeUndefined<T> = ExcludeUndefined<T>> = E extends BuiltIns
? E
: E extends Map<infer KeyType, infer ValueType>
? Map<RequiredDeep<KeyType>, RequiredDeep<ValueType>>
: E extends Set<infer ItemType>
? Set<RequiredDeep<ItemType>>
: E extends ReadonlyMap<infer KeyType, infer ValueType>
? ReadonlyMap<RequiredDeep<KeyType>, RequiredDeep<ValueType>>
: E extends ReadonlySet<infer ItemType>
? ReadonlySet<RequiredDeep<ItemType>>
: E extends WeakMap<infer KeyType, infer ValueType>
? WeakMap<RequiredDeep<KeyType>, RequiredDeep<ValueType>>
: E extends WeakSet<infer ItemType>
? WeakSet<RequiredDeep<ItemType>>
: E extends Promise<infer ValueType>
? Promise<RequiredDeep<ValueType>>
: E extends (...arguments_: any[]) => unknown
? {} extends RequiredObjectDeep<E>
? E
: HasMultipleCallSignatures<E> extends true
? E
: ((...arguments_: Parameters<E>) => ReturnType<E>) & RequiredObjectDeep<E>
: E extends object
? E extends Array<infer ItemType> // Test for arrays/tuples, per https://github.com/microsoft/TypeScript/issues/35156
? ItemType[] extends E // Test for arrays (non-tuples) specifically
? Array<RequiredDeep<ItemType>> // Recreate relevant array type to prevent eager evaluation of circular reference
: RequiredObjectDeep<E> // Tuples behave properly
: RequiredObjectDeep<E>
: unknown;
type RequiredObjectDeep<ObjectType extends object> = {
[KeyType in keyof ObjectType]-?: RequiredDeep<ObjectType[KeyType]>
};