Skip to content

Commit f14a75a

Browse files
authored
ConditionalPickDeep / SimplifyDeep: Prevent mapping over built-ins (#1293)
1 parent 8beaa89 commit f14a75a

File tree

4 files changed

+34
-20
lines changed

4 files changed

+34
-20
lines changed

source/internal/object.d.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import type {Simplify} from '../simplify.d.ts';
2-
import type {UnknownArray} from '../unknown-array.d.ts';
32
import type {IsEqual} from '../is-equal.d.ts';
43
import type {KeysOfUnion} from '../keys-of-union.d.ts';
54
import type {RequiredKeysOf} from '../required-keys-of.d.ts';
@@ -9,7 +8,7 @@ import type {IsAny} from '../is-any.d.ts';
98
import type {If} from '../if.d.ts';
109
import type {IsNever} from '../is-never.d.ts';
1110
import type {FilterDefinedKeys, FilterOptionalKeys} from './keys.d.ts';
12-
import type {NonRecursiveType} from './type.d.ts';
11+
import type {MapsSetsOrArrays, NonRecursiveType} from './type.d.ts';
1312
import type {ToString} from './string.d.ts';
1413

1514
/**
@@ -40,11 +39,13 @@ export type BuildObject<Key extends PropertyKey, Value, CopiedFrom extends objec
4039
Returns a boolean for whether the given type is a plain key-value object.
4140
*/
4241
export type IsPlainObject<T> =
43-
T extends NonRecursiveType | UnknownArray | ReadonlyMap<unknown, unknown> | ReadonlySet<unknown>
42+
IsNever<T> extends true
4443
? false
45-
: T extends object
46-
? true
47-
: false;
44+
: T extends NonRecursiveType | MapsSetsOrArrays
45+
? false
46+
: T extends object
47+
? true
48+
: false;
4849

4950
/**
5051
Extract the object field type if T is an object and K is a key of T, return `never` otherwise.

source/internal/type.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export type BuiltIns = Primitive | void | Date | RegExp;
1212
/**
1313
Matches non-recursive types.
1414
*/
15-
export type NonRecursiveType = BuiltIns | Function | (new (...arguments_: any[]) => unknown);
15+
export type NonRecursiveType = BuiltIns | Function | (new (...arguments_: any[]) => unknown) | Promise<unknown>;
1616

1717
/**
1818
Matches maps, sets, or arrays.

source/simplify-deep.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type {ConditionalSimplifyDeep} from './conditional-simplify-deep.d.ts';
2-
import type {NonRecursiveType} from './internal/index.d.ts';
2+
import type {MapsSetsOrArrays, NonRecursiveType} from './internal/index.d.ts';
33

44
/**
55
Deeply simplifies an object type.
@@ -110,7 +110,7 @@ type SimplifyDeepProperties = SimplifyDeep<Properties1 & Properties2, ComplexTyp
110110
export type SimplifyDeep<Type, ExcludeType = never> =
111111
ConditionalSimplifyDeep<
112112
Type,
113-
ExcludeType | NonRecursiveType | Set<unknown> | Map<unknown, unknown>,
113+
ExcludeType | NonRecursiveType | MapsSetsOrArrays,
114114
object
115115
>;
116116

test-d/conditional-pick-deep.ts

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,23 @@ type Example = {
1616
literal: 'foo';
1717
string: string;
1818
map: Map<string, string>;
19+
readonlyMap: ReadonlyMap<string, string>;
20+
weakMap: WeakMap<WeakKey, string>;
1921
set: Set<string>;
22+
readonlySet: ReadonlySet<string>;
23+
weakSet: WeakSet<WeakKey>;
2024
date: Date;
2125
number: 1;
2226
array: string[];
27+
readonlyArray: readonly string[];
2328
tuples: ['foo', 'bar'];
2429
interface: InterfaceA;
2530
instanceA: ClassA;
2631
ClassA: typeof ClassA;
2732
function: (...arguments_: string[]) => string;
33+
promise: Promise<string>;
2834
stringOrBoolean: string | boolean;
35+
never: never;
2936
object: {
3037
string: string;
3138
subObject: {
@@ -42,6 +49,7 @@ expectType<{
4249
instanceA: {
4350
a: string;
4451
};
52+
never: never;
4553
object: {
4654
string: string;
4755
subObject: {
@@ -71,6 +79,7 @@ expectType<{
7179
instanceA: {
7280
a: string;
7381
};
82+
never: never;
7483
object: {
7584
string: string;
7685
subObject: {
@@ -84,13 +93,16 @@ declare const stringPickOptionalOnly: ConditionalPickDeep<Example, string | unde
8493
expectType<{object: {subObject: {optional?: string}}}>(stringPickOptionalOnly);
8594

8695
declare const booleanPick: ConditionalPickDeep<Example, boolean | undefined>;
87-
expectType<{optional?: boolean; optionalWithUndefined?: boolean | undefined}>(booleanPick);
96+
expectType<{optional?: boolean; optionalWithUndefined?: boolean | undefined; never: never}>(booleanPick);
8897

8998
declare const numberPick: ConditionalPickDeep<Example, number>;
90-
expectType<{number: 1; interface: {a: number}}>(numberPick);
99+
expectType<{number: 1; interface: {a: number}; never: never}>(numberPick);
91100

92101
declare const emptyPick: ConditionalPickDeep<Example, 'abcdefg'>;
93-
expectType<{}>(emptyPick);
102+
expectType<{never: never}>(emptyPick);
103+
104+
declare const emptyEqualityPick: ConditionalPickDeep<Example, 'abcdefg', {condition: 'equality'}>;
105+
expectType<{}>(emptyEqualityPick);
94106

95107
declare const stringOrBooleanPick: ConditionalPickDeep<Example, string | boolean>;
96108
expectType<{
@@ -100,6 +112,7 @@ expectType<{
100112
instanceA: {
101113
a: string;
102114
};
115+
never: never;
103116
object: {
104117
string: string;
105118
subObject: {
@@ -112,28 +125,28 @@ declare const stringOrBooleanPickOnly: ConditionalPickDeep<Example, string | boo
112125
expectType<{stringOrBoolean: string | boolean}>(stringOrBooleanPickOnly);
113126

114127
declare const arrayPick: ConditionalPickDeep<Example, string[]>;
115-
expectType<{array: string[]; tuples: ['foo', 'bar']}>(arrayPick);
128+
expectType<{array: string[]; tuples: ['foo', 'bar']; never: never}>(arrayPick);
116129

117130
declare const arrayEqualityPick: ConditionalPickDeep<Example, string[], {condition: 'equality'}>;
118131
expectType<{array: string[]}>(arrayEqualityPick);
119132

120133
declare const tuplePick: ConditionalPickDeep<Example, ['foo', 'bar']>;
121-
expectType<{tuples: ['foo', 'bar']}>(tuplePick);
134+
expectType<{tuples: ['foo', 'bar']; never: never}>(tuplePick);
122135

123136
declare const instancePick: ConditionalPickDeep<Example, ClassA>;
124-
expectType<{instanceA: ClassA}>(instancePick);
137+
expectType<{instanceA: ClassA; never: never}>(instancePick);
125138

126139
declare const classPick: ConditionalPickDeep<Example, typeof ClassA>;
127-
expectType<{ClassA: typeof ClassA}>(classPick);
140+
expectType<{ClassA: typeof ClassA; never: never}>(classPick);
128141

129142
declare const functionPick: ConditionalPickDeep<Example, (...arguments_: string[]) => string>;
130-
expectType<{function: (...arguments_: string[]) => string}>(functionPick);
143+
expectType<{function: (...arguments_: string[]) => string; never: never}>(functionPick);
131144

132145
declare const mapPick: ConditionalPickDeep<Example, Map<string, string>>;
133-
expectType<{map: Map<string, string>}>(mapPick);
146+
expectType<{map: Map<string, string>; never: never}>(mapPick);
134147

135148
declare const setPick: ConditionalPickDeep<Example, Set<string>>;
136-
expectType<{set: Set<string>}>(setPick);
149+
expectType<{set: Set<string>; never: never}>(setPick);
137150

138151
declare const interfaceTest: ConditionalPickDeep<Example, InterfaceA>;
139-
expectType<{interface: InterfaceA}>(interfaceTest);
152+
expectType<{interface: InterfaceA; never: never}>(interfaceTest);

0 commit comments

Comments
 (0)