-
-
Notifications
You must be signed in to change notification settings - Fork 679
Expand file tree
/
Copy pathset-non-nullable-deep.d.ts
More file actions
85 lines (72 loc) · 2.76 KB
/
set-non-nullable-deep.d.ts
File metadata and controls
85 lines (72 loc) · 2.76 KB
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
79
80
81
82
83
84
85
import type {NonRecursiveType, StringToNumber} from './internal/index.d.ts';
import type {Paths} from './paths.d.ts';
import type {SetNonNullable} from './set-non-nullable.d.ts';
import type {Simplify} from './simplify.d.ts';
import type {UnionToTuple} from './union-to-tuple.d.ts';
import type {UnknownArray} from './unknown-array.d.ts';
/**
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.
NOTE: Optional modifiers (`?`) are not removed from properties. For example, `SetNonNullableDeep<{foo?: string | null | undefined}, 'foo'>` will result in `{foo?: string}`.
@example
```
import type {SetNonNullableDeep} from 'type-fest';
type User = {
name: string;
address: {
city: string | undefined;
street?: string | null;
};
contact: {
email?: string | null | undefined;
phone: string | undefined;
};
};
type UpdatedUser = SetNonNullableDeep<User, 'address.street' | 'contact.email' | 'contact.phone'>;
//=> {
// name: string;
// address: {
// city: string | undefined;
// street?: string;
// };
// contact: {
// email?: string;
// phone: string;
// };
// }
```
@example
```
import type {SetNonNullableDeep} from 'type-fest';
// Set specific indices in an array to be non-nullable.
type ArrayExample1 = SetNonNullableDeep<{a: [number | null, number | null, number | undefined]}, 'a.1' | 'a.2'>;
//=> {a: [number | null, number, number]}
// Optional modifier (`?`) is not removed.
type ArrayExample2 = SetNonNullableDeep<{a: [(number | null)?, (number | null)?]}, 'a.1'>;
//=> {a: [(number | null)?, number?]}
```
@category Object
*/
export type SetNonNullableDeep<BaseType, KeyPaths extends Paths<BaseType>> =
SetNonNullableDeepHelper<BaseType, UnionToTuple<KeyPaths>>;
/**
Internal helper for {@link SetNonNullableDeep}.
Recursively transforms the `BaseType` by applying {@link SetNonNullableDeepSinglePath} for each path in `KeyPathsTuple`.
*/
type SetNonNullableDeepHelper<BaseType, KeyPathsTuple extends UnknownArray> =
KeyPathsTuple extends [infer KeyPath, ...infer RestPaths]
? SetNonNullableDeepHelper<SetNonNullableDeepSinglePath<BaseType, KeyPath>, RestPaths>
: BaseType;
/**
Makes a single path non-nullable in `BaseType`.
*/
type SetNonNullableDeepSinglePath<BaseType, KeyPath> =
BaseType extends NonRecursiveType | ReadonlySet<unknown> | ReadonlyMap<unknown, unknown> // Also distributes `BaseType`
? BaseType
: KeyPath extends `${infer Property}.${infer RestPath}`
? {
[Key in keyof BaseType]: Property extends `${Key & (string | number)}`
? SetNonNullableDeepSinglePath<BaseType[Key], RestPath>
: BaseType[Key];
}
: Simplify<SetNonNullable<BaseType, (KeyPath | StringToNumber<KeyPath & string>) & keyof BaseType>>;
export {};