-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpick-all.ts
55 lines (54 loc) · 1.75 KB
/
pick-all.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
import type { KeyOf } from './key-of'
import type { UnionToIntersection } from './union-to-intersection'
/**
* Extract all properties from every member in a union type.
* Like `Pick`, properties are selected by key, but similar to `Extract`, the entire property is extracted `{key: value}`.
* If a property doesn't exist in all members of `Union`, the property is unioned with `Otherwise`.
*
* @param Union - A discriminated union type to extract properties from.
* @param Keys - The specific properties to extract from `Union`.
* @param Otherwise - The type to unionize with value types that don't exist in all members of `Union`.
* @defaultValue all `KeyOf<Union>`
* @defaultValue `undefined`
* @example
* Try extracting properties from a discriminated union type:
* ```ts
* declare const union: { kind: 0, str: 'str' } | { kind: 1, fn: () => void }
* type Union = typeof union
* ```
* @example
* Using `KeyOf<Union>` and `PickAll<Union>`:
* ```ts
* type PossibleUnionKeys = KeyOf<Union>
* // 'kind' | 'str' | 'fn' // ✅
*
* type PossibleUnionProps = PickAll<Union>
* // {
* // kind: 0 | 1;
* // str: 'str' | undefined;
* // fn: () => void | undefined
* // }
* // ✅
*
* type PossibleUnionValues = PickAll<Union>[UnionKeys]
* // 0 | 1 | 'str' | () => void | undefined // ✅
* ```
* @example
* #### Compare against standard indexed access with `keyof`:
* ```ts
* type _UnionKeys keyof Union
* // 'kind' // ❓ missing 'str' and 'fn'
*
* type _UnionValues Union[keyof Union]
* // 0 | 1 // ❓ missing 'str' and () => void
* ```
*/
export type PickAll<
Union,
Keys extends KeyOf<Union> = KeyOf<Union>,
Otherwise = undefined
> = {
[_K in Keys]: Union extends { [K in _K]: infer Value }
? UnionToIntersection<Value>
: Otherwise
}