Skip to content

Commit b0a387a

Browse files
committed
Address PR comments
And address bug with contextually typed arguments that the PR changes exposed.
1 parent aa38cdb commit b0a387a

File tree

5 files changed

+183
-88
lines changed

5 files changed

+183
-88
lines changed

src/compiler/checker.ts

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8520,15 +8520,14 @@ namespace ts {
85208520
function getContextuallyTypedParameterType(parameter: ParameterDeclaration): Type {
85218521
const func = parameter.parent;
85228522
if (isContextSensitiveFunctionOrObjectLiteralMethod(func)) {
8523-
if (isIife(func)) {
8523+
const iife = getImmediatelyInvokedFunctionExpression(func);
8524+
if (iife) {
85248525
const indexOfParameter = indexOf(func.parameters, parameter);
8525-
const call = func.parent.parent as CallExpression;
8526-
if (indexOfParameter < call.arguments.length) {
8527-
const type = getTypeOfExpression(call.arguments[indexOfParameter]);
8528-
if (type && parameter.dotDotDotToken) {
8529-
return createArrayType(type);
8526+
if (iife.arguments && indexOfParameter < iife.arguments.length) {
8527+
if (parameter.dotDotDotToken) {
8528+
return createArrayType(getUnionType(map(iife.arguments.slice(indexOfParameter), getTypeOfExpression)));
85308529
}
8531-
return type;
8530+
return checkExpression(iife.arguments[indexOfParameter], identityMapper);
85328531
}
85338532
}
85348533
const contextualSignature = getContextualSignature(func);
@@ -8551,11 +8550,16 @@ namespace ts {
85518550
return undefined;
85528551
}
85538552

8554-
function isIife(func: FunctionExpression | MethodDeclaration) {
8555-
return (func.kind === SyntaxKind.FunctionExpression || func.kind === SyntaxKind.ArrowFunction) &&
8556-
func.parent.kind === SyntaxKind.ParenthesizedExpression &&
8557-
func.parent.parent.kind === SyntaxKind.CallExpression &&
8558-
(func.parent.parent as CallExpression).expression === func.parent;
8553+
function getImmediatelyInvokedFunctionExpression(func: FunctionExpression | MethodDeclaration) {
8554+
if (isFunctionExpressionOrArrowFunction(func)) {
8555+
let parent = func.parent;
8556+
while (parent.kind === SyntaxKind.ParenthesizedExpression) {
8557+
parent = parent.parent;
8558+
}
8559+
if (parent.kind === SyntaxKind.CallExpression) {
8560+
return parent as CallExpression;
8561+
}
8562+
}
85598563
}
85608564

85618565
// In a variable, parameter or property declaration with a type annotation,

tests/baselines/reference/contextuallyTypedIife.js

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
(jake => { })("build");
44
// function expression
55
(function (cats) { })("lol");
6+
// Lots of Irritating Superfluous Parentheses
7+
(function (x) { } ("!"));
8+
((((function (y) { }))))("-");
69
// multiple arguments
710
((a, b, c) => { })("foo", 101, false);
8-
// contextually typed parameters.
9-
(f => f(1))(i => i + 1);
1011
// default parameters
1112
((m = 10) => m + 1)(12);
1213
((n = 10) => n + 1)();
@@ -16,26 +17,29 @@
1617
((l, o?) => l + o)(12); // o should be any
1718
// rest parameters
1819
((...numbers) => numbers.every(n => n > 0))(5,6,7);
20+
((...mixed) => mixed.every(n => !!n))(5,'oops','oh no');
1921
((...noNumbers) => noNumbers.some(n => n > 0))();
2022
((first, ...rest) => first ? [] : rest.map(n => n > 0))(8,9,10);
2123
// destructuring parameters (with defaults too!)
2224
(({ q }) => q)({ q : 13 });
2325
(({ p = 14 }) => p)({ p : 15 });
2426
(({ r = 17 } = { r: 18 }) => r)({r : 19});
2527
(({ u = 22 } = { u: 23 }) => u)();
26-
27-
28+
// contextually typed parameters.
29+
let twelve = (f => f(12))(i => i);
30+
let eleven = (o => o.a(11))({ a: function(n) { return n; } });
2831

2932

3033
//// [contextuallyTypedIife.js]
3134
// arrow
3235
(function (jake) { })("build");
3336
// function expression
3437
(function (cats) { })("lol");
38+
// Lots of Irritating Superfluous Parentheses
39+
(function (x) { }("!"));
40+
((((function (y) { }))))("-");
3541
// multiple arguments
3642
(function (a, b, c) { })("foo", 101, false);
37-
// contextually typed parameters.
38-
(function (f) { return f(1); })(function (i) { return i + 1; });
3943
// default parameters
4044
(function (m) {
4145
if (m === void 0) { m = 10; }
@@ -57,6 +61,13 @@
5761
}
5862
return numbers.every(function (n) { return n > 0; });
5963
})(5, 6, 7);
64+
(function () {
65+
var mixed = [];
66+
for (var _i = 0; _i < arguments.length; _i++) {
67+
mixed[_i - 0] = arguments[_i];
68+
}
69+
return mixed.every(function (n) { return !!n; });
70+
})(5, 'oops', 'oh no');
6071
(function () {
6172
var noNumbers = [];
6273
for (var _i = 0; _i < arguments.length; _i++) {
@@ -88,3 +99,6 @@
8899
var _b = (_a === void 0 ? { u: 23 } : _a).u, u = _b === void 0 ? 22 : _b;
89100
return u;
90101
})();
102+
// contextually typed parameters.
103+
var twelve = (function (f) { return f(12); })(function (i) { return i; });
104+
var eleven = (function (o) { return o.a(11); })({ a: function (n) { return n; } });

tests/baselines/reference/contextuallyTypedIife.symbols

Lines changed: 74 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -7,91 +7,115 @@
77
(function (cats) { })("lol");
88
>cats : Symbol(cats, Decl(contextuallyTypedIife.ts, 3, 11))
99

10+
// Lots of Irritating Superfluous Parentheses
11+
(function (x) { } ("!"));
12+
>x : Symbol(x, Decl(contextuallyTypedIife.ts, 5, 11))
13+
14+
((((function (y) { }))))("-");
15+
>y : Symbol(y, Decl(contextuallyTypedIife.ts, 6, 14))
16+
1017
// multiple arguments
1118
((a, b, c) => { })("foo", 101, false);
12-
>a : Symbol(a, Decl(contextuallyTypedIife.ts, 5, 2))
13-
>b : Symbol(b, Decl(contextuallyTypedIife.ts, 5, 4))
14-
>c : Symbol(c, Decl(contextuallyTypedIife.ts, 5, 7))
15-
16-
// contextually typed parameters.
17-
(f => f(1))(i => i + 1);
18-
>f : Symbol(f, Decl(contextuallyTypedIife.ts, 7, 1))
19-
>f : Symbol(f, Decl(contextuallyTypedIife.ts, 7, 1))
20-
>i : Symbol(i, Decl(contextuallyTypedIife.ts, 7, 12))
21-
>i : Symbol(i, Decl(contextuallyTypedIife.ts, 7, 12))
19+
>a : Symbol(a, Decl(contextuallyTypedIife.ts, 8, 2))
20+
>b : Symbol(b, Decl(contextuallyTypedIife.ts, 8, 4))
21+
>c : Symbol(c, Decl(contextuallyTypedIife.ts, 8, 7))
2222

2323
// default parameters
2424
((m = 10) => m + 1)(12);
25-
>m : Symbol(m, Decl(contextuallyTypedIife.ts, 9, 2))
26-
>m : Symbol(m, Decl(contextuallyTypedIife.ts, 9, 2))
25+
>m : Symbol(m, Decl(contextuallyTypedIife.ts, 10, 2))
26+
>m : Symbol(m, Decl(contextuallyTypedIife.ts, 10, 2))
2727

2828
((n = 10) => n + 1)();
29-
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 10, 2))
30-
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 10, 2))
29+
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 11, 2))
30+
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 11, 2))
3131

3232
// optional parameters
3333
((j?) => j + 1)(12);
34-
>j : Symbol(j, Decl(contextuallyTypedIife.ts, 12, 2))
35-
>j : Symbol(j, Decl(contextuallyTypedIife.ts, 12, 2))
34+
>j : Symbol(j, Decl(contextuallyTypedIife.ts, 13, 2))
35+
>j : Symbol(j, Decl(contextuallyTypedIife.ts, 13, 2))
3636

3737
((k?) => k + 1)();
38-
>k : Symbol(k, Decl(contextuallyTypedIife.ts, 13, 2))
39-
>k : Symbol(k, Decl(contextuallyTypedIife.ts, 13, 2))
38+
>k : Symbol(k, Decl(contextuallyTypedIife.ts, 14, 2))
39+
>k : Symbol(k, Decl(contextuallyTypedIife.ts, 14, 2))
4040

4141
((l, o?) => l + o)(12); // o should be any
42-
>l : Symbol(l, Decl(contextuallyTypedIife.ts, 14, 2))
43-
>o : Symbol(o, Decl(contextuallyTypedIife.ts, 14, 4))
44-
>l : Symbol(l, Decl(contextuallyTypedIife.ts, 14, 2))
45-
>o : Symbol(o, Decl(contextuallyTypedIife.ts, 14, 4))
42+
>l : Symbol(l, Decl(contextuallyTypedIife.ts, 15, 2))
43+
>o : Symbol(o, Decl(contextuallyTypedIife.ts, 15, 4))
44+
>l : Symbol(l, Decl(contextuallyTypedIife.ts, 15, 2))
45+
>o : Symbol(o, Decl(contextuallyTypedIife.ts, 15, 4))
4646

4747
// rest parameters
4848
((...numbers) => numbers.every(n => n > 0))(5,6,7);
49-
>numbers : Symbol(numbers, Decl(contextuallyTypedIife.ts, 16, 2))
49+
>numbers : Symbol(numbers, Decl(contextuallyTypedIife.ts, 17, 2))
5050
>numbers.every : Symbol(Array.every, Decl(lib.d.ts, --, --))
51-
>numbers : Symbol(numbers, Decl(contextuallyTypedIife.ts, 16, 2))
51+
>numbers : Symbol(numbers, Decl(contextuallyTypedIife.ts, 17, 2))
5252
>every : Symbol(Array.every, Decl(lib.d.ts, --, --))
53-
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 16, 31))
54-
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 16, 31))
53+
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 17, 31))
54+
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 17, 31))
55+
56+
((...mixed) => mixed.every(n => !!n))(5,'oops','oh no');
57+
>mixed : Symbol(mixed, Decl(contextuallyTypedIife.ts, 18, 2))
58+
>mixed.every : Symbol(Array.every, Decl(lib.d.ts, --, --))
59+
>mixed : Symbol(mixed, Decl(contextuallyTypedIife.ts, 18, 2))
60+
>every : Symbol(Array.every, Decl(lib.d.ts, --, --))
61+
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 18, 27))
62+
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 18, 27))
5563

5664
((...noNumbers) => noNumbers.some(n => n > 0))();
57-
>noNumbers : Symbol(noNumbers, Decl(contextuallyTypedIife.ts, 17, 2))
65+
>noNumbers : Symbol(noNumbers, Decl(contextuallyTypedIife.ts, 19, 2))
5866
>noNumbers.some : Symbol(Array.some, Decl(lib.d.ts, --, --))
59-
>noNumbers : Symbol(noNumbers, Decl(contextuallyTypedIife.ts, 17, 2))
67+
>noNumbers : Symbol(noNumbers, Decl(contextuallyTypedIife.ts, 19, 2))
6068
>some : Symbol(Array.some, Decl(lib.d.ts, --, --))
61-
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 17, 34))
62-
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 17, 34))
69+
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 19, 34))
70+
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 19, 34))
6371

6472
((first, ...rest) => first ? [] : rest.map(n => n > 0))(8,9,10);
65-
>first : Symbol(first, Decl(contextuallyTypedIife.ts, 18, 2))
66-
>rest : Symbol(rest, Decl(contextuallyTypedIife.ts, 18, 8))
67-
>first : Symbol(first, Decl(contextuallyTypedIife.ts, 18, 2))
73+
>first : Symbol(first, Decl(contextuallyTypedIife.ts, 20, 2))
74+
>rest : Symbol(rest, Decl(contextuallyTypedIife.ts, 20, 8))
75+
>first : Symbol(first, Decl(contextuallyTypedIife.ts, 20, 2))
6876
>rest.map : Symbol(Array.map, Decl(lib.d.ts, --, --))
69-
>rest : Symbol(rest, Decl(contextuallyTypedIife.ts, 18, 8))
77+
>rest : Symbol(rest, Decl(contextuallyTypedIife.ts, 20, 8))
7078
>map : Symbol(Array.map, Decl(lib.d.ts, --, --))
71-
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 18, 43))
72-
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 18, 43))
79+
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 20, 43))
80+
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 20, 43))
7381

7482
// destructuring parameters (with defaults too!)
7583
(({ q }) => q)({ q : 13 });
76-
>q : Symbol(q, Decl(contextuallyTypedIife.ts, 20, 3))
77-
>q : Symbol(q, Decl(contextuallyTypedIife.ts, 20, 3))
78-
>q : Symbol(q, Decl(contextuallyTypedIife.ts, 20, 16))
84+
>q : Symbol(q, Decl(contextuallyTypedIife.ts, 22, 3))
85+
>q : Symbol(q, Decl(contextuallyTypedIife.ts, 22, 3))
86+
>q : Symbol(q, Decl(contextuallyTypedIife.ts, 22, 16))
7987

8088
(({ p = 14 }) => p)({ p : 15 });
81-
>p : Symbol(p, Decl(contextuallyTypedIife.ts, 21, 3))
82-
>p : Symbol(p, Decl(contextuallyTypedIife.ts, 21, 3))
83-
>p : Symbol(p, Decl(contextuallyTypedIife.ts, 21, 21))
89+
>p : Symbol(p, Decl(contextuallyTypedIife.ts, 23, 3))
90+
>p : Symbol(p, Decl(contextuallyTypedIife.ts, 23, 3))
91+
>p : Symbol(p, Decl(contextuallyTypedIife.ts, 23, 21))
8492

8593
(({ r = 17 } = { r: 18 }) => r)({r : 19});
86-
>r : Symbol(r, Decl(contextuallyTypedIife.ts, 22, 3))
87-
>r : Symbol(r, Decl(contextuallyTypedIife.ts, 22, 16))
88-
>r : Symbol(r, Decl(contextuallyTypedIife.ts, 22, 3))
89-
>r : Symbol(r, Decl(contextuallyTypedIife.ts, 22, 33))
94+
>r : Symbol(r, Decl(contextuallyTypedIife.ts, 24, 3))
95+
>r : Symbol(r, Decl(contextuallyTypedIife.ts, 24, 16))
96+
>r : Symbol(r, Decl(contextuallyTypedIife.ts, 24, 3))
97+
>r : Symbol(r, Decl(contextuallyTypedIife.ts, 24, 33))
9098

9199
(({ u = 22 } = { u: 23 }) => u)();
92-
>u : Symbol(u, Decl(contextuallyTypedIife.ts, 23, 3))
93-
>u : Symbol(u, Decl(contextuallyTypedIife.ts, 23, 16))
94-
>u : Symbol(u, Decl(contextuallyTypedIife.ts, 23, 3))
95-
100+
>u : Symbol(u, Decl(contextuallyTypedIife.ts, 25, 3))
101+
>u : Symbol(u, Decl(contextuallyTypedIife.ts, 25, 16))
102+
>u : Symbol(u, Decl(contextuallyTypedIife.ts, 25, 3))
96103

104+
// contextually typed parameters.
105+
let twelve = (f => f(12))(i => i);
106+
>twelve : Symbol(twelve, Decl(contextuallyTypedIife.ts, 27, 3))
107+
>f : Symbol(f, Decl(contextuallyTypedIife.ts, 27, 14))
108+
>f : Symbol(f, Decl(contextuallyTypedIife.ts, 27, 14))
109+
>i : Symbol(i, Decl(contextuallyTypedIife.ts, 27, 26))
110+
>i : Symbol(i, Decl(contextuallyTypedIife.ts, 27, 26))
111+
112+
let eleven = (o => o.a(11))({ a: function(n) { return n; } });
113+
>eleven : Symbol(eleven, Decl(contextuallyTypedIife.ts, 28, 3))
114+
>o : Symbol(o, Decl(contextuallyTypedIife.ts, 28, 14))
115+
>o.a : Symbol(a, Decl(contextuallyTypedIife.ts, 28, 29))
116+
>o : Symbol(o, Decl(contextuallyTypedIife.ts, 28, 14))
117+
>a : Symbol(a, Decl(contextuallyTypedIife.ts, 28, 29))
118+
>a : Symbol(a, Decl(contextuallyTypedIife.ts, 28, 29))
119+
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 28, 42))
120+
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 28, 42))
97121

tests/baselines/reference/contextuallyTypedIife.types

Lines changed: 66 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,24 @@
1515
>cats : string
1616
>"lol" : string
1717

18+
// Lots of Irritating Superfluous Parentheses
19+
(function (x) { } ("!"));
20+
>(function (x) { } ("!")) : void
21+
>function (x) { } ("!") : void
22+
>function (x) { } : (x: string) => void
23+
>x : string
24+
>"!" : string
25+
26+
((((function (y) { }))))("-");
27+
>((((function (y) { }))))("-") : void
28+
>((((function (y) { })))) : (y: string) => void
29+
>(((function (y) { }))) : (y: string) => void
30+
>((function (y) { })) : (y: string) => void
31+
>(function (y) { }) : (y: string) => void
32+
>function (y) { } : (y: string) => void
33+
>y : string
34+
>"-" : string
35+
1836
// multiple arguments
1937
((a, b, c) => { })("foo", 101, false);
2038
>((a, b, c) => { })("foo", 101, false) : void
@@ -27,21 +45,6 @@
2745
>101 : number
2846
>false : boolean
2947

30-
// contextually typed parameters.
31-
(f => f(1))(i => i + 1);
32-
>(f => f(1))(i => i + 1) : any
33-
>(f => f(1)) : (f: (i: any) => any) => any
34-
>f => f(1) : (f: (i: any) => any) => any
35-
>f : (i: any) => any
36-
>f(1) : any
37-
>f : (i: any) => any
38-
>1 : number
39-
>i => i + 1 : (i: any) => any
40-
>i : any
41-
>i + 1 : any
42-
>i : any
43-
>1 : number
44-
4548
// default parameters
4649
((m = 10) => m + 1)(12);
4750
>((m = 10) => m + 1)(12) : number
@@ -114,6 +117,24 @@
114117
>6 : number
115118
>7 : number
116119

120+
((...mixed) => mixed.every(n => !!n))(5,'oops','oh no');
121+
>((...mixed) => mixed.every(n => !!n))(5,'oops','oh no') : boolean
122+
>((...mixed) => mixed.every(n => !!n)) : (...mixed: (number | string)[]) => boolean
123+
>(...mixed) => mixed.every(n => !!n) : (...mixed: (number | string)[]) => boolean
124+
>mixed : (number | string)[]
125+
>mixed.every(n => !!n) : boolean
126+
>mixed.every : (callbackfn: (value: number | string, index: number, array: (number | string)[]) => boolean, thisArg?: any) => boolean
127+
>mixed : (number | string)[]
128+
>every : (callbackfn: (value: number | string, index: number, array: (number | string)[]) => boolean, thisArg?: any) => boolean
129+
>n => !!n : (n: number | string) => boolean
130+
>n : number | string
131+
>!!n : boolean
132+
>!n : boolean
133+
>n : number | string
134+
>5 : number
135+
>'oops' : string
136+
>'oh no' : string
137+
117138
((...noNumbers) => noNumbers.some(n => n > 0))();
118139
>((...noNumbers) => noNumbers.some(n => n > 0))() : boolean
119140
>((...noNumbers) => noNumbers.some(n => n > 0)) : (...noNumbers: any[]) => boolean
@@ -198,5 +219,34 @@
198219
>23 : number
199220
>u : number
200221

201-
222+
// contextually typed parameters.
223+
let twelve = (f => f(12))(i => i);
224+
>twelve : any
225+
>(f => f(12))(i => i) : any
226+
>(f => f(12)) : (f: {}) => any
227+
>f => f(12) : (f: {}) => any
228+
>f : {}
229+
>f(12) : any
230+
>f : {}
231+
>12 : number
232+
>i => i : (i: {}) => {}
233+
>i : {}
234+
>i : {}
235+
236+
let eleven = (o => o.a(11))({ a: function(n) { return n; } });
237+
>eleven : any
238+
>(o => o.a(11))({ a: function(n) { return n; } }) : any
239+
>(o => o.a(11)) : (o: { a: {}; }) => any
240+
>o => o.a(11) : (o: { a: {}; }) => any
241+
>o : { a: {}; }
242+
>o.a(11) : any
243+
>o.a : {}
244+
>o : { a: {}; }
245+
>a : {}
246+
>11 : number
247+
>{ a: function(n) { return n; } } : { a: (n: any) => any; }
248+
>a : (n: any) => any
249+
>function(n) { return n; } : (n: any) => any
250+
>n : any
251+
>n : any
202252

0 commit comments

Comments
 (0)