Address PR comments

And address bug with contextually typed arguments that the PR changes
exposed.
This commit is contained in:
Nathan Shively-Sanders
2016-05-05 15:04:17 -07:00
parent aa38cdba56
commit b0a387aafa
5 changed files with 181 additions and 86 deletions
+16 -12
View File
@@ -8520,15 +8520,14 @@ namespace ts {
function getContextuallyTypedParameterType(parameter: ParameterDeclaration): Type {
const func = parameter.parent;
if (isContextSensitiveFunctionOrObjectLiteralMethod(func)) {
if (isIife(func)) {
const iife = getImmediatelyInvokedFunctionExpression(func);
if (iife) {
const indexOfParameter = indexOf(func.parameters, parameter);
const call = func.parent.parent as CallExpression;
if (indexOfParameter < call.arguments.length) {
const type = getTypeOfExpression(call.arguments[indexOfParameter]);
if (type && parameter.dotDotDotToken) {
return createArrayType(type);
if (iife.arguments && indexOfParameter < iife.arguments.length) {
if (parameter.dotDotDotToken) {
return createArrayType(getUnionType(map(iife.arguments.slice(indexOfParameter), getTypeOfExpression)));
}
return type;
return checkExpression(iife.arguments[indexOfParameter], identityMapper);
}
}
const contextualSignature = getContextualSignature(func);
@@ -8551,11 +8550,16 @@ namespace ts {
return undefined;
}
function isIife(func: FunctionExpression | MethodDeclaration) {
return (func.kind === SyntaxKind.FunctionExpression || func.kind === SyntaxKind.ArrowFunction) &&
func.parent.kind === SyntaxKind.ParenthesizedExpression &&
func.parent.parent.kind === SyntaxKind.CallExpression &&
(func.parent.parent as CallExpression).expression === func.parent;
function getImmediatelyInvokedFunctionExpression(func: FunctionExpression | MethodDeclaration) {
if (isFunctionExpressionOrArrowFunction(func)) {
let parent = func.parent;
while (parent.kind === SyntaxKind.ParenthesizedExpression) {
parent = parent.parent;
}
if (parent.kind === SyntaxKind.CallExpression) {
return parent as CallExpression;
}
}
}
// In a variable, parameter or property declaration with a type annotation,
@@ -3,10 +3,11 @@
(jake => { })("build");
// function expression
(function (cats) { })("lol");
// Lots of Irritating Superfluous Parentheses
(function (x) { } ("!"));
((((function (y) { }))))("-");
// multiple arguments
((a, b, c) => { })("foo", 101, false);
// contextually typed parameters.
(f => f(1))(i => i + 1);
// default parameters
((m = 10) => m + 1)(12);
((n = 10) => n + 1)();
@@ -16,6 +17,7 @@
((l, o?) => l + o)(12); // o should be any
// rest parameters
((...numbers) => numbers.every(n => n > 0))(5,6,7);
((...mixed) => mixed.every(n => !!n))(5,'oops','oh no');
((...noNumbers) => noNumbers.some(n => n > 0))();
((first, ...rest) => first ? [] : rest.map(n => n > 0))(8,9,10);
// destructuring parameters (with defaults too!)
@@ -23,8 +25,9 @@
(({ p = 14 }) => p)({ p : 15 });
(({ r = 17 } = { r: 18 }) => r)({r : 19});
(({ u = 22 } = { u: 23 }) => u)();
// contextually typed parameters.
let twelve = (f => f(12))(i => i);
let eleven = (o => o.a(11))({ a: function(n) { return n; } });
//// [contextuallyTypedIife.js]
@@ -32,10 +35,11 @@
(function (jake) { })("build");
// function expression
(function (cats) { })("lol");
// Lots of Irritating Superfluous Parentheses
(function (x) { }("!"));
((((function (y) { }))))("-");
// multiple arguments
(function (a, b, c) { })("foo", 101, false);
// contextually typed parameters.
(function (f) { return f(1); })(function (i) { return i + 1; });
// default parameters
(function (m) {
if (m === void 0) { m = 10; }
@@ -57,6 +61,13 @@
}
return numbers.every(function (n) { return n > 0; });
})(5, 6, 7);
(function () {
var mixed = [];
for (var _i = 0; _i < arguments.length; _i++) {
mixed[_i - 0] = arguments[_i];
}
return mixed.every(function (n) { return !!n; });
})(5, 'oops', 'oh no');
(function () {
var noNumbers = [];
for (var _i = 0; _i < arguments.length; _i++) {
@@ -88,3 +99,6 @@
var _b = (_a === void 0 ? { u: 23 } : _a).u, u = _b === void 0 ? 22 : _b;
return u;
})();
// contextually typed parameters.
var twelve = (function (f) { return f(12); })(function (i) { return i; });
var eleven = (function (o) { return o.a(11); })({ a: function (n) { return n; } });
@@ -7,91 +7,115 @@
(function (cats) { })("lol");
>cats : Symbol(cats, Decl(contextuallyTypedIife.ts, 3, 11))
// Lots of Irritating Superfluous Parentheses
(function (x) { } ("!"));
>x : Symbol(x, Decl(contextuallyTypedIife.ts, 5, 11))
((((function (y) { }))))("-");
>y : Symbol(y, Decl(contextuallyTypedIife.ts, 6, 14))
// multiple arguments
((a, b, c) => { })("foo", 101, false);
>a : Symbol(a, Decl(contextuallyTypedIife.ts, 5, 2))
>b : Symbol(b, Decl(contextuallyTypedIife.ts, 5, 4))
>c : Symbol(c, Decl(contextuallyTypedIife.ts, 5, 7))
// contextually typed parameters.
(f => f(1))(i => i + 1);
>f : Symbol(f, Decl(contextuallyTypedIife.ts, 7, 1))
>f : Symbol(f, Decl(contextuallyTypedIife.ts, 7, 1))
>i : Symbol(i, Decl(contextuallyTypedIife.ts, 7, 12))
>i : Symbol(i, Decl(contextuallyTypedIife.ts, 7, 12))
>a : Symbol(a, Decl(contextuallyTypedIife.ts, 8, 2))
>b : Symbol(b, Decl(contextuallyTypedIife.ts, 8, 4))
>c : Symbol(c, Decl(contextuallyTypedIife.ts, 8, 7))
// default parameters
((m = 10) => m + 1)(12);
>m : Symbol(m, Decl(contextuallyTypedIife.ts, 9, 2))
>m : Symbol(m, Decl(contextuallyTypedIife.ts, 9, 2))
>m : Symbol(m, Decl(contextuallyTypedIife.ts, 10, 2))
>m : Symbol(m, Decl(contextuallyTypedIife.ts, 10, 2))
((n = 10) => n + 1)();
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 10, 2))
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 10, 2))
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 11, 2))
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 11, 2))
// optional parameters
((j?) => j + 1)(12);
>j : Symbol(j, Decl(contextuallyTypedIife.ts, 12, 2))
>j : Symbol(j, Decl(contextuallyTypedIife.ts, 12, 2))
>j : Symbol(j, Decl(contextuallyTypedIife.ts, 13, 2))
>j : Symbol(j, Decl(contextuallyTypedIife.ts, 13, 2))
((k?) => k + 1)();
>k : Symbol(k, Decl(contextuallyTypedIife.ts, 13, 2))
>k : Symbol(k, Decl(contextuallyTypedIife.ts, 13, 2))
>k : Symbol(k, Decl(contextuallyTypedIife.ts, 14, 2))
>k : Symbol(k, Decl(contextuallyTypedIife.ts, 14, 2))
((l, o?) => l + o)(12); // o should be any
>l : Symbol(l, Decl(contextuallyTypedIife.ts, 14, 2))
>o : Symbol(o, Decl(contextuallyTypedIife.ts, 14, 4))
>l : Symbol(l, Decl(contextuallyTypedIife.ts, 14, 2))
>o : Symbol(o, Decl(contextuallyTypedIife.ts, 14, 4))
>l : Symbol(l, Decl(contextuallyTypedIife.ts, 15, 2))
>o : Symbol(o, Decl(contextuallyTypedIife.ts, 15, 4))
>l : Symbol(l, Decl(contextuallyTypedIife.ts, 15, 2))
>o : Symbol(o, Decl(contextuallyTypedIife.ts, 15, 4))
// rest parameters
((...numbers) => numbers.every(n => n > 0))(5,6,7);
>numbers : Symbol(numbers, Decl(contextuallyTypedIife.ts, 16, 2))
>numbers : Symbol(numbers, Decl(contextuallyTypedIife.ts, 17, 2))
>numbers.every : Symbol(Array.every, Decl(lib.d.ts, --, --))
>numbers : Symbol(numbers, Decl(contextuallyTypedIife.ts, 16, 2))
>numbers : Symbol(numbers, Decl(contextuallyTypedIife.ts, 17, 2))
>every : Symbol(Array.every, Decl(lib.d.ts, --, --))
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 16, 31))
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 16, 31))
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 17, 31))
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 17, 31))
((...mixed) => mixed.every(n => !!n))(5,'oops','oh no');
>mixed : Symbol(mixed, Decl(contextuallyTypedIife.ts, 18, 2))
>mixed.every : Symbol(Array.every, Decl(lib.d.ts, --, --))
>mixed : Symbol(mixed, Decl(contextuallyTypedIife.ts, 18, 2))
>every : Symbol(Array.every, Decl(lib.d.ts, --, --))
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 18, 27))
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 18, 27))
((...noNumbers) => noNumbers.some(n => n > 0))();
>noNumbers : Symbol(noNumbers, Decl(contextuallyTypedIife.ts, 17, 2))
>noNumbers : Symbol(noNumbers, Decl(contextuallyTypedIife.ts, 19, 2))
>noNumbers.some : Symbol(Array.some, Decl(lib.d.ts, --, --))
>noNumbers : Symbol(noNumbers, Decl(contextuallyTypedIife.ts, 17, 2))
>noNumbers : Symbol(noNumbers, Decl(contextuallyTypedIife.ts, 19, 2))
>some : Symbol(Array.some, Decl(lib.d.ts, --, --))
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 17, 34))
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 17, 34))
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 19, 34))
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 19, 34))
((first, ...rest) => first ? [] : rest.map(n => n > 0))(8,9,10);
>first : Symbol(first, Decl(contextuallyTypedIife.ts, 18, 2))
>rest : Symbol(rest, Decl(contextuallyTypedIife.ts, 18, 8))
>first : Symbol(first, Decl(contextuallyTypedIife.ts, 18, 2))
>first : Symbol(first, Decl(contextuallyTypedIife.ts, 20, 2))
>rest : Symbol(rest, Decl(contextuallyTypedIife.ts, 20, 8))
>first : Symbol(first, Decl(contextuallyTypedIife.ts, 20, 2))
>rest.map : Symbol(Array.map, Decl(lib.d.ts, --, --))
>rest : Symbol(rest, Decl(contextuallyTypedIife.ts, 18, 8))
>rest : Symbol(rest, Decl(contextuallyTypedIife.ts, 20, 8))
>map : Symbol(Array.map, Decl(lib.d.ts, --, --))
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 18, 43))
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 18, 43))
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 20, 43))
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 20, 43))
// destructuring parameters (with defaults too!)
(({ q }) => q)({ q : 13 });
>q : Symbol(q, Decl(contextuallyTypedIife.ts, 20, 3))
>q : Symbol(q, Decl(contextuallyTypedIife.ts, 20, 3))
>q : Symbol(q, Decl(contextuallyTypedIife.ts, 20, 16))
>q : Symbol(q, Decl(contextuallyTypedIife.ts, 22, 3))
>q : Symbol(q, Decl(contextuallyTypedIife.ts, 22, 3))
>q : Symbol(q, Decl(contextuallyTypedIife.ts, 22, 16))
(({ p = 14 }) => p)({ p : 15 });
>p : Symbol(p, Decl(contextuallyTypedIife.ts, 21, 3))
>p : Symbol(p, Decl(contextuallyTypedIife.ts, 21, 3))
>p : Symbol(p, Decl(contextuallyTypedIife.ts, 21, 21))
>p : Symbol(p, Decl(contextuallyTypedIife.ts, 23, 3))
>p : Symbol(p, Decl(contextuallyTypedIife.ts, 23, 3))
>p : Symbol(p, Decl(contextuallyTypedIife.ts, 23, 21))
(({ r = 17 } = { r: 18 }) => r)({r : 19});
>r : Symbol(r, Decl(contextuallyTypedIife.ts, 22, 3))
>r : Symbol(r, Decl(contextuallyTypedIife.ts, 22, 16))
>r : Symbol(r, Decl(contextuallyTypedIife.ts, 22, 3))
>r : Symbol(r, Decl(contextuallyTypedIife.ts, 22, 33))
>r : Symbol(r, Decl(contextuallyTypedIife.ts, 24, 3))
>r : Symbol(r, Decl(contextuallyTypedIife.ts, 24, 16))
>r : Symbol(r, Decl(contextuallyTypedIife.ts, 24, 3))
>r : Symbol(r, Decl(contextuallyTypedIife.ts, 24, 33))
(({ u = 22 } = { u: 23 }) => u)();
>u : Symbol(u, Decl(contextuallyTypedIife.ts, 23, 3))
>u : Symbol(u, Decl(contextuallyTypedIife.ts, 23, 16))
>u : Symbol(u, Decl(contextuallyTypedIife.ts, 23, 3))
>u : Symbol(u, Decl(contextuallyTypedIife.ts, 25, 3))
>u : Symbol(u, Decl(contextuallyTypedIife.ts, 25, 16))
>u : Symbol(u, Decl(contextuallyTypedIife.ts, 25, 3))
// contextually typed parameters.
let twelve = (f => f(12))(i => i);
>twelve : Symbol(twelve, Decl(contextuallyTypedIife.ts, 27, 3))
>f : Symbol(f, Decl(contextuallyTypedIife.ts, 27, 14))
>f : Symbol(f, Decl(contextuallyTypedIife.ts, 27, 14))
>i : Symbol(i, Decl(contextuallyTypedIife.ts, 27, 26))
>i : Symbol(i, Decl(contextuallyTypedIife.ts, 27, 26))
let eleven = (o => o.a(11))({ a: function(n) { return n; } });
>eleven : Symbol(eleven, Decl(contextuallyTypedIife.ts, 28, 3))
>o : Symbol(o, Decl(contextuallyTypedIife.ts, 28, 14))
>o.a : Symbol(a, Decl(contextuallyTypedIife.ts, 28, 29))
>o : Symbol(o, Decl(contextuallyTypedIife.ts, 28, 14))
>a : Symbol(a, Decl(contextuallyTypedIife.ts, 28, 29))
>a : Symbol(a, Decl(contextuallyTypedIife.ts, 28, 29))
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 28, 42))
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 28, 42))
@@ -15,6 +15,24 @@
>cats : string
>"lol" : string
// Lots of Irritating Superfluous Parentheses
(function (x) { } ("!"));
>(function (x) { } ("!")) : void
>function (x) { } ("!") : void
>function (x) { } : (x: string) => void
>x : string
>"!" : string
((((function (y) { }))))("-");
>((((function (y) { }))))("-") : void
>((((function (y) { })))) : (y: string) => void
>(((function (y) { }))) : (y: string) => void
>((function (y) { })) : (y: string) => void
>(function (y) { }) : (y: string) => void
>function (y) { } : (y: string) => void
>y : string
>"-" : string
// multiple arguments
((a, b, c) => { })("foo", 101, false);
>((a, b, c) => { })("foo", 101, false) : void
@@ -27,21 +45,6 @@
>101 : number
>false : boolean
// contextually typed parameters.
(f => f(1))(i => i + 1);
>(f => f(1))(i => i + 1) : any
>(f => f(1)) : (f: (i: any) => any) => any
>f => f(1) : (f: (i: any) => any) => any
>f : (i: any) => any
>f(1) : any
>f : (i: any) => any
>1 : number
>i => i + 1 : (i: any) => any
>i : any
>i + 1 : any
>i : any
>1 : number
// default parameters
((m = 10) => m + 1)(12);
>((m = 10) => m + 1)(12) : number
@@ -114,6 +117,24 @@
>6 : number
>7 : number
((...mixed) => mixed.every(n => !!n))(5,'oops','oh no');
>((...mixed) => mixed.every(n => !!n))(5,'oops','oh no') : boolean
>((...mixed) => mixed.every(n => !!n)) : (...mixed: (number | string)[]) => boolean
>(...mixed) => mixed.every(n => !!n) : (...mixed: (number | string)[]) => boolean
>mixed : (number | string)[]
>mixed.every(n => !!n) : boolean
>mixed.every : (callbackfn: (value: number | string, index: number, array: (number | string)[]) => boolean, thisArg?: any) => boolean
>mixed : (number | string)[]
>every : (callbackfn: (value: number | string, index: number, array: (number | string)[]) => boolean, thisArg?: any) => boolean
>n => !!n : (n: number | string) => boolean
>n : number | string
>!!n : boolean
>!n : boolean
>n : number | string
>5 : number
>'oops' : string
>'oh no' : string
((...noNumbers) => noNumbers.some(n => n > 0))();
>((...noNumbers) => noNumbers.some(n => n > 0))() : boolean
>((...noNumbers) => noNumbers.some(n => n > 0)) : (...noNumbers: any[]) => boolean
@@ -198,5 +219,34 @@
>23 : number
>u : number
// contextually typed parameters.
let twelve = (f => f(12))(i => i);
>twelve : any
>(f => f(12))(i => i) : any
>(f => f(12)) : (f: {}) => any
>f => f(12) : (f: {}) => any
>f : {}
>f(12) : any
>f : {}
>12 : number
>i => i : (i: {}) => {}
>i : {}
>i : {}
let eleven = (o => o.a(11))({ a: function(n) { return n; } });
>eleven : any
>(o => o.a(11))({ a: function(n) { return n; } }) : any
>(o => o.a(11)) : (o: { a: {}; }) => any
>o => o.a(11) : (o: { a: {}; }) => any
>o : { a: {}; }
>o.a(11) : any
>o.a : {}
>o : { a: {}; }
>a : {}
>11 : number
>{ a: function(n) { return n; } } : { a: (n: any) => any; }
>a : (n: any) => any
>function(n) { return n; } : (n: any) => any
>n : any
>n : any
@@ -2,10 +2,11 @@
(jake => { })("build");
// function expression
(function (cats) { })("lol");
// Lots of Irritating Superfluous Parentheses
(function (x) { } ("!"));
((((function (y) { }))))("-");
// multiple arguments
((a, b, c) => { })("foo", 101, false);
// contextually typed parameters.
(f => f(1))(i => i + 1);
// default parameters
((m = 10) => m + 1)(12);
((n = 10) => n + 1)();
@@ -15,6 +16,7 @@
((l, o?) => l + o)(12); // o should be any
// rest parameters
((...numbers) => numbers.every(n => n > 0))(5,6,7);
((...mixed) => mixed.every(n => !!n))(5,'oops','oh no');
((...noNumbers) => noNumbers.some(n => n > 0))();
((first, ...rest) => first ? [] : rest.map(n => n > 0))(8,9,10);
// destructuring parameters (with defaults too!)
@@ -22,5 +24,6 @@
(({ p = 14 }) => p)({ p : 15 });
(({ r = 17 } = { r: 18 }) => r)({r : 19});
(({ u = 22 } = { u: 23 }) => u)();
// contextually typed parameters.
let twelve = (f => f(12))(i => i);
let eleven = (o => o.a(11))({ a: function(n) { return n; } });