forked from sindresorhus/type-fest
-
Notifications
You must be signed in to change notification settings - Fork 0
/
conditional-pick-deep.d.ts
104 lines (87 loc) · 2.64 KB
/
conditional-pick-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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import type {IsEqual} from './is-equal';
import type {ConditionalExcept} from './conditional-except';
import type {ConditionalSimplifyDeep} from './conditional-simplify';
import type {UnknownRecord} from './unknown-record';
import type {EmptyObject} from './empty-object';
import type {IsPlainObject} from './internal';
/**
Used to mark properties that should be excluded.
*/
declare const conditionalPickDeepSymbol: unique symbol;
/**
Assert the condition according to the {@link ConditionalPickDeepOptions.condition|condition} option.
*/
type AssertCondition<Type, Condition, Options extends ConditionalPickDeepOptions> = Options['condition'] extends 'equality'
? IsEqual<Type, Condition>
: Type extends Condition
? true
: false;
/**
ConditionalPickDeep options.
@see ConditionalPickDeep
*/
export type ConditionalPickDeepOptions = {
/**
The condition assertion mode.
@default 'extends'
*/
condition?: 'extends' | 'equality';
};
/**
Pick keys recursively from the shape that matches the given condition.
@see ConditionalPick
@example
```
import type {ConditionalPickDeep} from 'type-fest';
interface Example {
a: string;
b: string | boolean;
c: {
d: string;
e: {
f?: string;
g?: boolean;
h: string | boolean;
i: boolean | bigint;
};
j: boolean;
};
}
type StringPick = ConditionalPickDeep<Example, string>;
//=> {a: string; c: {d: string}}
type StringPickOptional = ConditionalPickDeep<Example, string | undefined>;
//=> {a: string; c: {d: string; e: {f?: string}}}
type StringPickOptionalOnly = ConditionalPickDeep<Example, string | undefined, {condition: 'equality'}>;
//=> {c: {e: {f?: string}}}
type BooleanPick = ConditionalPickDeep<Example, boolean | undefined>;
//=> {c: {e: {g?: boolean}; j: boolean}}
type NumberPick = ConditionalPickDeep<Example, number>;
//=> {}
type StringOrBooleanPick = ConditionalPickDeep<Example, string | boolean>;
//=> {
// a: string;
// b: string | boolean;
// c: {
// d: string;
// e: {
// h: string | boolean
// };
// j: boolean;
// };
// }
type StringOrBooleanPickOnly = ConditionalPickDeep<Example, string | boolean, {condition: 'equality'}>;
//=> {b: string | boolean; c: {e: {h: string | boolean}}}
```
@category Object
*/
export type ConditionalPickDeep<
Type,
Condition,
Options extends ConditionalPickDeepOptions = {},
> = ConditionalSimplifyDeep<ConditionalExcept<{
[Key in keyof Type]: AssertCondition<Type[Key], Condition, Options> extends true
? Type[Key]
: IsPlainObject<Type[Key]> extends true
? ConditionalPickDeep<Type[Key], Condition, Options>
: typeof conditionalPickDeepSymbol;
}, (typeof conditionalPickDeepSymbol | undefined) | EmptyObject>, never, UnknownRecord>;