Skip to content

Commit 9960ba4

Browse files
authoredOct 30, 2023
ConditionalPickDeep: Ensure it doesn't recurse into prototype properties (#736)
1 parent b9723d4 commit 9960ba4

File tree

2 files changed

+92
-23
lines changed

2 files changed

+92
-23
lines changed
 

‎source/conditional-pick-deep.d.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import type {IsEqual} from './is-equal';
22
import type {ConditionalExcept} from './conditional-except';
33
import type {ConditionalSimplifyDeep} from './conditional-simplify';
4+
import type {UnknownRecord} from './unknown-record';
5+
import type {EmptyObject} from './empty-object';
46

57
/**
68
Used to mark properties that should be excluded.
@@ -95,7 +97,7 @@ export type ConditionalPickDeep<
9597
> = ConditionalSimplifyDeep<ConditionalExcept<{
9698
[Key in keyof Type]: AssertCondition<Type[Key], Condition, Options> extends true
9799
? Type[Key]
98-
: Type[Key] extends object
100+
: Type[Key] extends UnknownRecord
99101
? ConditionalPickDeep<Type[Key], Condition, Options>
100102
: typeof conditionalPickDeepSymbol;
101-
}, (typeof conditionalPickDeepSymbol | undefined) | Record<PropertyKey, never>>>;
103+
}, (typeof conditionalPickDeepSymbol | undefined) | EmptyObject>, never, UnknownRecord>;

‎test-d/conditional-pick-deep.ts

+88-21
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,113 @@
11
import {expectType} from 'tsd';
22
import type {ConditionalPickDeep} from '../index';
33

4+
declare class ClassA {
5+
public a: string;
6+
}
7+
48
type Example = {
5-
a: string;
6-
b: string | boolean;
7-
c: {
8-
d: string;
9-
e: {
10-
f?: string;
11-
g?: boolean;
12-
h: string | boolean;
13-
i: boolean | bigint;
9+
optional?: boolean;
10+
literal: 'foo';
11+
string: string;
12+
map: Map<string, string>;
13+
set: Set<string>;
14+
date: Date;
15+
array: string[];
16+
tuples: ['foo', 'bar'];
17+
instanceA: ClassA;
18+
ClassA: typeof ClassA;
19+
function: (...args: string[]) => string;
20+
stringOrBoolean: string | boolean;
21+
object: {
22+
string: string;
23+
subObject: {
24+
optional?: string;
25+
string: string;
1426
};
15-
j: boolean;
1627
};
1728
};
1829

1930
declare const stringPick: ConditionalPickDeep<Example, string>;
20-
expectType<{a: string; c: {d: string}}>(stringPick);
31+
expectType<{
32+
literal: 'foo';
33+
string: string;
34+
object: {
35+
string: string;
36+
subObject: {
37+
string: string;
38+
};
39+
};
40+
}>(stringPick);
41+
42+
declare const stringEqualityPick: ConditionalPickDeep<Example, string, {condition: 'equality'}>;
43+
expectType<{
44+
string: string;
45+
object: {
46+
string: string;
47+
subObject: {
48+
string: string;
49+
};
50+
};
51+
}>(stringEqualityPick);
2152

2253
declare const stringPickOptional: ConditionalPickDeep<Example, string | undefined>;
23-
expectType<{a: string; c: {d: string; e: {f?: string}}}>(stringPickOptional);
54+
expectType<{
55+
literal: 'foo';
56+
string: string;
57+
object: {
58+
string: string;
59+
subObject: {
60+
optional?: string | undefined;
61+
string: string;
62+
};
63+
};
64+
}>(stringPickOptional);
2465

2566
declare const stringPickOptionalOnly: ConditionalPickDeep<Example, string | undefined, {condition: 'equality'}>;
26-
expectType<{c: {e: {f?: string}}}>(stringPickOptionalOnly);
67+
expectType<{object: {subObject: {optional?: string | undefined}}}>(stringPickOptionalOnly);
2768

2869
declare const booleanPick: ConditionalPickDeep<Example, boolean | undefined>;
29-
expectType<{c: {e: {g?: boolean}; j: boolean}}>(booleanPick);
70+
expectType<{optional?: boolean | undefined}>(booleanPick);
3071

3172
declare const numberPick: ConditionalPickDeep<Example, number>;
3273
expectType<{}>(numberPick);
3374

3475
declare const stringOrBooleanPick: ConditionalPickDeep<Example, string | boolean>;
3576
expectType<{
36-
a: string;
37-
b: string | boolean;
38-
c: {
39-
d: string;
40-
e: {h: string | boolean};
41-
j: boolean;
77+
literal: 'foo';
78+
string: string;
79+
stringOrBoolean: string | boolean;
80+
object: {
81+
string: string;
82+
subObject: {
83+
string: string;
84+
};
4285
};
4386
}>(stringOrBooleanPick);
4487

4588
declare const stringOrBooleanPickOnly: ConditionalPickDeep<Example, string | boolean, {condition: 'equality'}>;
46-
expectType<{b: string | boolean; c: {e: {h: string | boolean}}}>(stringOrBooleanPickOnly);
89+
expectType<{stringOrBoolean: string | boolean}>(stringOrBooleanPickOnly);
90+
91+
declare const arrayPick: ConditionalPickDeep<Example, string[]>;
92+
expectType<{array: string[]; tuples: ['foo', 'bar']}>(arrayPick);
93+
94+
declare const arrayEqualityPick: ConditionalPickDeep<Example, string[], {condition: 'equality'}>;
95+
expectType<{array: string[]}>(arrayEqualityPick);
96+
97+
declare const tuplePick: ConditionalPickDeep<Example, ['foo', 'bar']>;
98+
expectType<{tuples: ['foo', 'bar']}>(tuplePick);
99+
100+
declare const instancePick: ConditionalPickDeep<Example, ClassA>;
101+
expectType<{instanceA: ClassA}>(instancePick);
102+
103+
declare const classPick: ConditionalPickDeep<Example, typeof ClassA>;
104+
expectType<{ClassA: typeof ClassA}>(classPick);
105+
106+
declare const functionPick: ConditionalPickDeep<Example, (...args: string[]) => string>;
107+
expectType<{function: (...args: string[]) => string}>(functionPick);
108+
109+
declare const mapPick: ConditionalPickDeep<Example, Map<string, string>>;
110+
expectType<{map: Map<string, string>}>(mapPick);
111+
112+
declare const setPick: ConditionalPickDeep<Example, Set<string>>;
113+
expectType<{set: Set<string>}>(setPick);

0 commit comments

Comments
 (0)
Please sign in to comment.