-
-
Notifications
You must be signed in to change notification settings - Fork 576
/
Copy pathall-union-fields.d.ts
88 lines (75 loc) · 2.24 KB
/
all-union-fields.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
79
80
81
82
83
84
85
86
87
88
import type {NonRecursiveType, ReadonlyKeysOfUnion, ValueOfUnion} from './internal';
import type {KeysOfUnion} from './keys-of-union';
import type {SharedUnionFields} from './shared-union-fields';
import type {Simplify} from './simplify';
import type {UnknownArray} from './unknown-array';
/**
Create a type with all fields from a union of object types.
Use-cases:
- You want a safe object type where each key exists in the union object.
@example
```
import type {AllUnionFields} from 'type-fest';
type Cat = {
name: string;
type: 'cat';
catType: string;
};
type Dog = {
name: string;
type: 'dog';
dogType: string;
};
function displayPetInfo(petInfo: Cat | Dog) {
// typeof petInfo =>
// {
// name: string;
// type: 'cat';
// catType: string;
// } | {
// name: string;
// type: 'dog';
// dogType: string;
// }
console.log('name: ', petInfo.name);
console.log('type: ', petInfo.type);
// TypeScript complains about `catType` and `dogType` not existing on type `Cat | Dog`.
console.log('animal type: ', petInfo.catType ?? petInfo.dogType);
}
function displayPetInfo(petInfo: AllUnionFields<Cat | Dog>) {
// typeof petInfo =>
// {
// name: string;
// type: 'cat' | 'dog';
// catType?: string;
// dogType?: string;
// }
console.log('name: ', petInfo.name);
console.log('type: ', petInfo.type);
// No TypeScript error.
console.log('animal type: ', petInfo.catType ?? petInfo.dogType);
}
```
@see SharedUnionFields
@category Object
@category Union
*/
export type AllUnionFields<Union> =
Extract<Union, NonRecursiveType | ReadonlyMap<unknown, unknown> | ReadonlySet<unknown> | UnknownArray> extends infer SkippedMembers
? Exclude<Union, SkippedMembers> extends infer RelevantMembers
?
| SkippedMembers
| Simplify<
// Include fields that are common in all union members
SharedUnionFields<RelevantMembers> &
// Include readonly fields present in any union member
{
readonly [P in ReadonlyKeysOfUnion<RelevantMembers>]?: ValueOfUnion<RelevantMembers, P & KeysOfUnion<RelevantMembers>>
} &
// Include remaining fields that are neither common nor readonly
{
[P in Exclude<KeysOfUnion<RelevantMembers>, ReadonlyKeysOfUnion<RelevantMembers> | keyof RelevantMembers>]?: ValueOfUnion<RelevantMembers, P>
}
>
: never
: never;