Skip to content

Commit 8a0b882

Browse files
authored
Fix contextually typed parameter issues (microsoft#36476)
* Fix multiple issues with contextually typed parameters * Accept new baselines * Fix lint error * Add tests * Address CR feedback * Add fourslash tests
1 parent 140fee9 commit 8a0b882

11 files changed

+861
-179
lines changed

src/compiler/checker.ts

Lines changed: 71 additions & 82 deletions
Large diffs are not rendered by default.
Lines changed: 63 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,54 @@
1-
tests/cases/compiler/contextuallyTypedParametersWithInitializers.ts(8,29): error TS7031: Binding element 'foo' implicitly has an 'any' type.
2-
tests/cases/compiler/contextuallyTypedParametersWithInitializers.ts(14,27): error TS7006: Parameter 'foo' implicitly has an 'any' type.
3-
tests/cases/compiler/contextuallyTypedParametersWithInitializers.ts(27,42): error TS7031: Binding element 'foo' implicitly has an 'any' type.
1+
tests/cases/compiler/contextuallyTypedParametersWithInitializers.ts(24,24): error TS7006: Parameter 'x' implicitly has an 'any' type.
2+
tests/cases/compiler/contextuallyTypedParametersWithInitializers.ts(40,5): error TS7006: Parameter 'x' implicitly has an 'any' type.
43

54

6-
==== tests/cases/compiler/contextuallyTypedParametersWithInitializers.ts (3 errors) ====
5+
==== tests/cases/compiler/contextuallyTypedParametersWithInitializers.ts (2 errors) ====
76
declare function id1<T>(input: T): T;
87
declare function id2<T extends (x: any) => any>(input: T): T;
98
declare function id3<T extends (x: { foo: any }) => any>(input: T): T;
109
declare function id4<T extends (x: { foo?: number }) => any>(input: T): T;
1110
declare function id5<T extends (x?: number) => any>(input: T): T;
1211

1312
const f10 = function ({ foo = 42 }) { return foo };
14-
const f11 = id1(function ({ foo = 42 }) { return foo }); // Implicit any error
15-
~~~
16-
!!! error TS7031: Binding element 'foo' implicitly has an 'any' type.
13+
const f11 = id1(function ({ foo = 42 }) { return foo });
1714
const f12 = id2(function ({ foo = 42 }) { return foo });
1815
const f13 = id3(function ({ foo = 42 }) { return foo });
1916
const f14 = id4(function ({ foo = 42 }) { return foo });
2017

2118
const f20 = function (foo = 42) { return foo };
22-
const f21 = id1(function (foo = 42) { return foo }); // Implicit any error
23-
~~~~~~~~
24-
!!! error TS7006: Parameter 'foo' implicitly has an 'any' type.
19+
const f21 = id1(function (foo = 42) { return foo });
2520
const f22 = id2(function (foo = 42) { return foo });
2621
const f25 = id5(function (foo = 42) { return foo });
2722

23+
const f1 = (x = 1) => 0; // number
24+
const f2: any = (x = 1) => 0; // number
25+
const f3: unknown = (x = 1) => 0; // number
26+
const f4: Function = (x = 1) => 0; // number
27+
const f5: (...args: any[]) => any = (x = 1) => 0; // any
28+
const f6: () => any = (x = 1) => 0; // number
29+
const f7: () => any = (x?) => 0; // Implicit any error
30+
~~
31+
!!! error TS7006: Parameter 'x' implicitly has an 'any' type.
32+
const f8: () => any = (...x) => 0; // []
33+
34+
declare function g1<T>(x: T): T;
35+
declare function g2<T extends any>(x: T): T;
36+
declare function g3<T extends unknown>(x: T): T;
37+
declare function g4<T extends Function>(x: T): T;
38+
declare function g5<T extends (...args: any[]) => any>(x: T): T;
39+
declare function g6<T extends () => any>(x: T): T;
40+
41+
g1((x = 1) => 0); // number
42+
g2((x = 1) => 0); // number
43+
g3((x = 1) => 0); // number
44+
g4((x = 1) => 0); // number
45+
g5((x = 1) => 0); // any
46+
g6((x = 1) => 0); // number
47+
g6((x?) => 0); // Implicit any error
48+
~~
49+
!!! error TS7006: Parameter 'x' implicitly has an 'any' type.
50+
g6((...x) => 0); // []
51+
2852
// Repro from #28816
2953

3054
function id<T>(input: T): T { return input }
@@ -35,8 +59,35 @@ tests/cases/compiler/contextuallyTypedParametersWithInitializers.ts(27,42): erro
3559

3660
const newGetFoo = id(getFoo);
3761
const newGetFoo2 = id(function getFoo ({ foo = 42 }) {
38-
~~~
39-
!!! error TS7031: Binding element 'foo' implicitly has an 'any' type.
4062
return foo;
4163
});
64+
65+
// Repro from comment in #30840
66+
67+
declare function memoize<F extends Function>(func: F): F;
68+
69+
function add(x: number, y = 0): number {
70+
return x + y;
71+
}
72+
const memoizedAdd = memoize(add);
73+
74+
const add2 = (x: number, y = 0): number => x + y;
75+
const memoizedAdd2 = memoize(add2);
76+
77+
const memoizedAdd3 = memoize((x: number, y = 0): number => x + y);
78+
79+
// Repro from #36052
80+
81+
declare function execute(script: string | Function): Promise<string>;
82+
83+
export function executeSomething() {
84+
return execute((root: HTMLElement, debug = true) => {
85+
if (debug) {
86+
root.innerHTML = '';
87+
}
88+
});
89+
}
90+
91+
const fz1 = (debug = true) => false;
92+
const fz2: Function = (debug = true) => false;
4293

tests/baselines/reference/contextuallyTypedParametersWithInitializers.js

Lines changed: 155 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,41 @@ declare function id4<T extends (x: { foo?: number }) => any>(input: T): T;
66
declare function id5<T extends (x?: number) => any>(input: T): T;
77

88
const f10 = function ({ foo = 42 }) { return foo };
9-
const f11 = id1(function ({ foo = 42 }) { return foo }); // Implicit any error
9+
const f11 = id1(function ({ foo = 42 }) { return foo });
1010
const f12 = id2(function ({ foo = 42 }) { return foo });
1111
const f13 = id3(function ({ foo = 42 }) { return foo });
1212
const f14 = id4(function ({ foo = 42 }) { return foo });
1313

1414
const f20 = function (foo = 42) { return foo };
15-
const f21 = id1(function (foo = 42) { return foo }); // Implicit any error
15+
const f21 = id1(function (foo = 42) { return foo });
1616
const f22 = id2(function (foo = 42) { return foo });
1717
const f25 = id5(function (foo = 42) { return foo });
1818

19+
const f1 = (x = 1) => 0; // number
20+
const f2: any = (x = 1) => 0; // number
21+
const f3: unknown = (x = 1) => 0; // number
22+
const f4: Function = (x = 1) => 0; // number
23+
const f5: (...args: any[]) => any = (x = 1) => 0; // any
24+
const f6: () => any = (x = 1) => 0; // number
25+
const f7: () => any = (x?) => 0; // Implicit any error
26+
const f8: () => any = (...x) => 0; // []
27+
28+
declare function g1<T>(x: T): T;
29+
declare function g2<T extends any>(x: T): T;
30+
declare function g3<T extends unknown>(x: T): T;
31+
declare function g4<T extends Function>(x: T): T;
32+
declare function g5<T extends (...args: any[]) => any>(x: T): T;
33+
declare function g6<T extends () => any>(x: T): T;
34+
35+
g1((x = 1) => 0); // number
36+
g2((x = 1) => 0); // number
37+
g3((x = 1) => 0); // number
38+
g4((x = 1) => 0); // number
39+
g5((x = 1) => 0); // any
40+
g6((x = 1) => 0); // number
41+
g6((x?) => 0); // Implicit any error
42+
g6((...x) => 0); // []
43+
1944
// Repro from #28816
2045

2146
function id<T>(input: T): T { return input }
@@ -28,18 +53,48 @@ const newGetFoo = id(getFoo);
2853
const newGetFoo2 = id(function getFoo ({ foo = 42 }) {
2954
return foo;
3055
});
56+
57+
// Repro from comment in #30840
58+
59+
declare function memoize<F extends Function>(func: F): F;
60+
61+
function add(x: number, y = 0): number {
62+
return x + y;
63+
}
64+
const memoizedAdd = memoize(add);
65+
66+
const add2 = (x: number, y = 0): number => x + y;
67+
const memoizedAdd2 = memoize(add2);
68+
69+
const memoizedAdd3 = memoize((x: number, y = 0): number => x + y);
70+
71+
// Repro from #36052
72+
73+
declare function execute(script: string | Function): Promise<string>;
74+
75+
export function executeSomething() {
76+
return execute((root: HTMLElement, debug = true) => {
77+
if (debug) {
78+
root.innerHTML = '';
79+
}
80+
});
81+
}
82+
83+
const fz1 = (debug = true) => false;
84+
const fz2: Function = (debug = true) => false;
3185

3286

3387
//// [contextuallyTypedParametersWithInitializers.js]
3488
"use strict";
89+
exports.__esModule = true;
3590
var f10 = function (_a) {
3691
var _b = _a.foo, foo = _b === void 0 ? 42 : _b;
3792
return foo;
3893
};
3994
var f11 = id1(function (_a) {
4095
var _b = _a.foo, foo = _b === void 0 ? 42 : _b;
4196
return foo;
42-
}); // Implicit any error
97+
});
4398
var f12 = id2(function (_a) {
4499
var _b = _a.foo, foo = _b === void 0 ? 42 : _b;
45100
return foo;
@@ -59,7 +114,7 @@ var f20 = function (foo) {
59114
var f21 = id1(function (foo) {
60115
if (foo === void 0) { foo = 42; }
61116
return foo;
62-
}); // Implicit any error
117+
});
63118
var f22 = id2(function (foo) {
64119
if (foo === void 0) { foo = 42; }
65120
return foo;
@@ -68,6 +123,70 @@ var f25 = id5(function (foo) {
68123
if (foo === void 0) { foo = 42; }
69124
return foo;
70125
});
126+
var f1 = function (x) {
127+
if (x === void 0) { x = 1; }
128+
return 0;
129+
}; // number
130+
var f2 = function (x) {
131+
if (x === void 0) { x = 1; }
132+
return 0;
133+
}; // number
134+
var f3 = function (x) {
135+
if (x === void 0) { x = 1; }
136+
return 0;
137+
}; // number
138+
var f4 = function (x) {
139+
if (x === void 0) { x = 1; }
140+
return 0;
141+
}; // number
142+
var f5 = function (x) {
143+
if (x === void 0) { x = 1; }
144+
return 0;
145+
}; // any
146+
var f6 = function (x) {
147+
if (x === void 0) { x = 1; }
148+
return 0;
149+
}; // number
150+
var f7 = function (x) { return 0; }; // Implicit any error
151+
var f8 = function () {
152+
var x = [];
153+
for (var _i = 0; _i < arguments.length; _i++) {
154+
x[_i] = arguments[_i];
155+
}
156+
return 0;
157+
}; // []
158+
g1(function (x) {
159+
if (x === void 0) { x = 1; }
160+
return 0;
161+
}); // number
162+
g2(function (x) {
163+
if (x === void 0) { x = 1; }
164+
return 0;
165+
}); // number
166+
g3(function (x) {
167+
if (x === void 0) { x = 1; }
168+
return 0;
169+
}); // number
170+
g4(function (x) {
171+
if (x === void 0) { x = 1; }
172+
return 0;
173+
}); // number
174+
g5(function (x) {
175+
if (x === void 0) { x = 1; }
176+
return 0;
177+
}); // any
178+
g6(function (x) {
179+
if (x === void 0) { x = 1; }
180+
return 0;
181+
}); // number
182+
g6(function (x) { return 0; }); // Implicit any error
183+
g6(function () {
184+
var x = [];
185+
for (var _i = 0; _i < arguments.length; _i++) {
186+
x[_i] = arguments[_i];
187+
}
188+
return 0;
189+
}); // []
71190
// Repro from #28816
72191
function id(input) { return input; }
73192
function getFoo(_a) {
@@ -79,36 +198,38 @@ var newGetFoo2 = id(function getFoo(_a) {
79198
var _b = _a.foo, foo = _b === void 0 ? 42 : _b;
80199
return foo;
81200
});
201+
function add(x, y) {
202+
if (y === void 0) { y = 0; }
203+
return x + y;
204+
}
205+
var memoizedAdd = memoize(add);
206+
var add2 = function (x, y) {
207+
if (y === void 0) { y = 0; }
208+
return x + y;
209+
};
210+
var memoizedAdd2 = memoize(add2);
211+
var memoizedAdd3 = memoize(function (x, y) {
212+
if (y === void 0) { y = 0; }
213+
return x + y;
214+
});
215+
function executeSomething() {
216+
return execute(function (root, debug) {
217+
if (debug === void 0) { debug = true; }
218+
if (debug) {
219+
root.innerHTML = '';
220+
}
221+
});
222+
}
223+
exports.executeSomething = executeSomething;
224+
var fz1 = function (debug) {
225+
if (debug === void 0) { debug = true; }
226+
return false;
227+
};
228+
var fz2 = function (debug) {
229+
if (debug === void 0) { debug = true; }
230+
return false;
231+
};
82232

83233

84234
//// [contextuallyTypedParametersWithInitializers.d.ts]
85-
declare function id1<T>(input: T): T;
86-
declare function id2<T extends (x: any) => any>(input: T): T;
87-
declare function id3<T extends (x: {
88-
foo: any;
89-
}) => any>(input: T): T;
90-
declare function id4<T extends (x: {
91-
foo?: number;
92-
}) => any>(input: T): T;
93-
declare function id5<T extends (x?: number) => any>(input: T): T;
94-
declare const f10: ({ foo }: {
95-
foo?: number | undefined;
96-
}) => number;
97-
declare const f11: ({ foo }: any) => any;
98-
declare const f12: ({ foo }: any) => any;
99-
declare const f13: ({ foo }: {
100-
foo: any;
101-
}) => any;
102-
declare const f14: ({ foo }: {
103-
foo?: number | undefined;
104-
}) => number;
105-
declare const f20: (foo?: number) => number;
106-
declare const f21: (foo?: any) => any;
107-
declare const f22: (foo?: any) => any;
108-
declare const f25: (foo?: number | undefined) => number;
109-
declare function id<T>(input: T): T;
110-
declare function getFoo({ foo }: {
111-
foo?: number | undefined;
112-
}): number;
113-
declare const newGetFoo: typeof getFoo;
114-
declare const newGetFoo2: ({ foo }: any) => any;
235+
export declare function executeSomething(): Promise<string>;

0 commit comments

Comments
 (0)