UNPKG

2.71 kBTypeScriptView Raw
1import type {IsEqual} from './is-equal';
2import type {ConditionalExcept} from './conditional-except';
3import type {ConditionalSimplifyDeep} from './conditional-simplify';
4import type {UnknownRecord} from './unknown-record';
5import type {EmptyObject} from './empty-object';
6import type {IsPlainObject} from './internal';
7
8/**
9Used to mark properties that should be excluded.
10*/
11declare const conditionalPickDeepSymbol: unique symbol;
12
13/**
14Assert the condition according to the {@link ConditionalPickDeepOptions.condition|condition} option.
15*/
16type AssertCondition<Type, Condition, Options extends ConditionalPickDeepOptions> = Options['condition'] extends 'equality'
17 ? IsEqual<Type, Condition>
18 : Type extends Condition
19 ? true
20 : false;
21
22/**
23ConditionalPickDeep options.
24
25@see ConditionalPickDeep
26*/
27export type ConditionalPickDeepOptions = {
28 /**
29 The condition assertion mode.
30
31 @default 'extends'
32 */
33 condition?: 'extends' | 'equality';
34};
35
36/**
37Pick keys recursively from the shape that matches the given condition.
38
39@see ConditionalPick
40
41@example
42```
43import type {ConditionalPickDeep} from 'type-fest';
44
45interface Example {
46 a: string;
47 b: string | boolean;
48 c: {
49 d: string;
50 e: {
51 f?: string;
52 g?: boolean;
53 h: string | boolean;
54 i: boolean | bigint;
55 };
56 j: boolean;
57 };
58}
59
60type StringPick = ConditionalPickDeep<Example, string>;
61//=> {a: string; c: {d: string}}
62
63type StringPickOptional = ConditionalPickDeep<Example, string | undefined>;
64//=> {a: string; c: {d: string; e: {f?: string}}}
65
66type StringPickOptionalOnly = ConditionalPickDeep<Example, string | undefined, {condition: 'equality'}>;
67//=> {c: {e: {f?: string}}}
68
69type BooleanPick = ConditionalPickDeep<Example, boolean | undefined>;
70//=> {c: {e: {g?: boolean}; j: boolean}}
71
72type NumberPick = ConditionalPickDeep<Example, number>;
73//=> {}
74
75type StringOrBooleanPick = ConditionalPickDeep<Example, string | boolean>;
76//=> {
77// a: string;
78// b: string | boolean;
79// c: {
80// d: string;
81// e: {
82// h: string | boolean
83// };
84// j: boolean;
85// };
86// }
87
88type StringOrBooleanPickOnly = ConditionalPickDeep<Example, string | boolean, {condition: 'equality'}>;
89//=> {b: string | boolean; c: {e: {h: string | boolean}}}
90```
91
92@category Object
93*/
94export type ConditionalPickDeep<
95 Type,
96 Condition,
97 Options extends ConditionalPickDeepOptions = {},
98> = ConditionalSimplifyDeep<ConditionalExcept<{
99 [Key in keyof Type]: AssertCondition<Type[Key], Condition, Options> extends true
100 ? Type[Key]
101 : IsPlainObject<Type[Key]> extends true
102 ? ConditionalPickDeep<Type[Key], Condition, Options>
103 : typeof conditionalPickDeepSymbol;
104}, (typeof conditionalPickDeepSymbol | undefined) | EmptyObject>, never, UnknownRecord>;