Skip to content

Commit 3bd9de6

Browse files
authored
PartialDeep: Fix behavior with functions containing multiple call signatures (#1259)
1 parent 590efae commit 3bd9de6

File tree

4 files changed

+32
-22
lines changed

4 files changed

+32
-22
lines changed

source/partial-deep.d.ts

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type {ApplyDefaultOptions, BuiltIns} from './internal/index.d.ts';
1+
import type {ApplyDefaultOptions, BuiltIns, HasMultipleCallSignatures} from './internal/index.d.ts';
22
import type {IsNever} from './is-never.d.ts';
33

44
/**
@@ -99,16 +99,20 @@ export type PartialDeep<T, Options extends PartialDeepOptions = {}> =
9999

100100
type _PartialDeep<T, Options extends Required<PartialDeepOptions>> = T extends BuiltIns | ((new (...arguments_: any[]) => unknown))
101101
? T
102-
: IsNever<keyof T> extends true // For functions with no properties
103-
? T
104-
: T extends Map<infer KeyType, infer ValueType>
105-
? PartialMapDeep<KeyType, ValueType, Options>
106-
: T extends Set<infer ItemType>
107-
? PartialSetDeep<ItemType, Options>
108-
: T extends ReadonlyMap<infer KeyType, infer ValueType>
109-
? PartialReadonlyMapDeep<KeyType, ValueType, Options>
110-
: T extends ReadonlySet<infer ItemType>
111-
? PartialReadonlySetDeep<ItemType, Options>
102+
: T extends Map<infer KeyType, infer ValueType>
103+
? PartialMapDeep<KeyType, ValueType, Options>
104+
: T extends Set<infer ItemType>
105+
? PartialSetDeep<ItemType, Options>
106+
: T extends ReadonlyMap<infer KeyType, infer ValueType>
107+
? PartialReadonlyMapDeep<KeyType, ValueType, Options>
108+
: T extends ReadonlySet<infer ItemType>
109+
? PartialReadonlySetDeep<ItemType, Options>
110+
: T extends (...arguments_: any[]) => unknown
111+
? IsNever<keyof T> extends true
112+
? T // For functions with no properties
113+
: HasMultipleCallSignatures<T> extends true
114+
? T
115+
: ((...arguments_: Parameters<T>) => ReturnType<T>) & PartialObjectDeep<T, Options>
112116
: T extends object
113117
? T extends ReadonlyArray<infer ItemType> // Test for arrays/tuples, per https://github.com/microsoft/TypeScript/issues/35156
114118
? Options['recurseIntoArrays'] extends true
@@ -144,11 +148,8 @@ type PartialReadonlySetDeep<T, Options extends Required<PartialDeepOptions>> = {
144148
/**
145149
Same as `PartialDeep`, but accepts only `object`s as inputs. Internal helper for `PartialDeep`.
146150
*/
147-
type PartialObjectDeep<ObjectType extends object, Options extends Required<PartialDeepOptions>> =
148-
(ObjectType extends (...arguments_: any) => unknown
149-
? (...arguments_: Parameters<ObjectType>) => ReturnType<ObjectType>
150-
: {}) & ({
151-
[KeyType in keyof ObjectType]?: _PartialDeep<ObjectType[KeyType], Options>
152-
});
151+
type PartialObjectDeep<ObjectType extends object, Options extends Required<PartialDeepOptions>> = {
152+
[KeyType in keyof ObjectType]?: _PartialDeep<ObjectType[KeyType], Options>
153+
};
153154

154155
export {};

source/required-deep.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type {BuiltIns, HasMultipleCallSignatures} from './internal/index.d.ts';
2+
import type {IsNever} from './is-never.d.ts';
23

34
/**
45
Create a type from another type with all keys and nested keys set to required.
@@ -58,7 +59,7 @@ export type RequiredDeep<T> = T extends BuiltIns
5859
: T extends Promise<infer ValueType>
5960
? Promise<RequiredDeep<ValueType>>
6061
: T extends (...arguments_: any[]) => unknown
61-
? {} extends RequiredObjectDeep<T>
62+
? IsNever<keyof T> extends true
6263
? T
6364
: HasMultipleCallSignatures<T> extends true
6465
? T

test-d/partial-deep.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {expectType, expectAssignable} from 'tsd';
1+
import {expectType, expectAssignable, expectNotType} from 'tsd';
22
import type {PartialDeep, Simplify} from '../index.d.ts';
33

44
class ClassA {
@@ -128,3 +128,10 @@ expectType<{p1?: {p2?: string; p3?: [{p4?: number}?, string?]}}>({} as Simplify<
128128

129129
expectType<{p1?: string[]}>({} as Simplify<PartialDeep<{(): void; p1: string[]}, {allowUndefinedInNonTupleArrays: false}>>);
130130
expectType<{p1?: string[]}>({} as Simplify<PartialDeep<{(): void; p1: string[]}, {allowUndefinedInNonTupleArrays: true}>>);
131+
132+
// Properties within functions containing multiple call signatures are not made partial due to TS limitations, refer https://github.com/microsoft/TypeScript/issues/29732
133+
type FunctionWithProperties4 = {(a1: number): string; (a1: string, a2: number): number; p1: string};
134+
declare const functionWithProperties4: PartialDeep<FunctionWithProperties4>;
135+
expectType<string>(functionWithProperties4(1));
136+
expectType<number>(functionWithProperties4('foo', 1));
137+
expectNotType<{p1?: string}>({} as Simplify<typeof functionWithProperties4>);

test-d/required-deep.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {expectType} from 'tsd';
1+
import {expectNotType, expectType} from 'tsd';
22
import type {RequiredDeep, Simplify} from '../index.d.ts';
33
import type {BuiltIns} from '../source/internal/type.d.ts';
44

@@ -80,5 +80,6 @@ expectType<{p1: {p2: string; p3: [{p4: number}, string]}}>({} as Simplify<typeof
8080
// Properties within functions containing multiple call signatures are not made required due to TS limitations, refer https://github.com/microsoft/TypeScript/issues/29732
8181
type FunctionWithProperties4 = {(a1: number): string; (a1: string, a2: number): number; p1?: string};
8282
declare const functionWithProperties4: RequiredDeep<FunctionWithProperties4>;
83-
// @ts-expect-error
84-
expectType<{p1: string}>({} as Simplify<typeof functionWithProperties4>);
83+
expectType<string>(functionWithProperties4(1));
84+
expectType<number>(functionWithProperties4('foo', 1));
85+
expectNotType<{p1: string}>({} as Simplify<typeof functionWithProperties4>);

0 commit comments

Comments
 (0)