A function should be context-sensitive if its return expression is (#17697)

* A function should be context-sensitive if its return expression is

* Remove outdated comment

* Fix typo
This commit is contained in:
Andy 2017-08-10 07:08:24 -07:00 committed by GitHub
parent 4c824505ad
commit fe3a05e89a
9 changed files with 75 additions and 28 deletions

View file

@ -8405,16 +8405,17 @@ namespace ts {
if (forEach(node.parameters, p => !getEffectiveTypeAnnotationNode(p))) {
return true;
}
// For arrow functions we now know we're not context sensitive.
if (node.kind === SyntaxKind.ArrowFunction) {
return false;
if (node.kind !== SyntaxKind.ArrowFunction) {
// If the first parameter is not an explicit 'this' parameter, then the function has
// an implicit 'this' parameter which is subject to contextual typing.
const parameter = firstOrUndefined(node.parameters);
if (!(parameter && parameterIsThisKeyword(parameter))) {
return true;
}
}
// If the first parameter is not an explicit 'this' parameter, then the function has
// an implicit 'this' parameter which is subject to contextual typing. Otherwise we
// know that all parameters (including 'this') have type annotations and nothing is
// subject to contextual typing.
const parameter = firstOrUndefined(node.parameters);
return !(parameter && parameterIsThisKeyword(parameter));
// TODO(anhans): A block should be context-sensitive if it has a context-sensitive return value.
return node.body.kind === SyntaxKind.Block ? false : isContextSensitive(node.body);
}
function isContextSensitiveFunctionOrObjectLiteralMethod(func: Node): func is FunctionExpression | ArrowFunction | MethodDeclaration {

View file

@ -0,0 +1,9 @@
//// [contextualTypingFunctionReturningFunction2.ts]
declare function f(n: number): void;
declare function f(cb: () => (n: number) => number): void;
f(() => n => n);
//// [contextualTypingFunctionReturningFunction2.js]
f(function () { return function (n) { return n; }; });

View file

@ -0,0 +1,15 @@
=== tests/cases/compiler/contextualTypingFunctionReturningFunction2.ts ===
declare function f(n: number): void;
>f : Symbol(f, Decl(contextualTypingFunctionReturningFunction2.ts, 0, 0), Decl(contextualTypingFunctionReturningFunction2.ts, 0, 36))
>n : Symbol(n, Decl(contextualTypingFunctionReturningFunction2.ts, 0, 19))
declare function f(cb: () => (n: number) => number): void;
>f : Symbol(f, Decl(contextualTypingFunctionReturningFunction2.ts, 0, 0), Decl(contextualTypingFunctionReturningFunction2.ts, 0, 36))
>cb : Symbol(cb, Decl(contextualTypingFunctionReturningFunction2.ts, 1, 19))
>n : Symbol(n, Decl(contextualTypingFunctionReturningFunction2.ts, 1, 30))
f(() => n => n);
>f : Symbol(f, Decl(contextualTypingFunctionReturningFunction2.ts, 0, 0), Decl(contextualTypingFunctionReturningFunction2.ts, 0, 36))
>n : Symbol(n, Decl(contextualTypingFunctionReturningFunction2.ts, 3, 7))
>n : Symbol(n, Decl(contextualTypingFunctionReturningFunction2.ts, 3, 7))

View file

@ -0,0 +1,18 @@
=== tests/cases/compiler/contextualTypingFunctionReturningFunction2.ts ===
declare function f(n: number): void;
>f : { (n: number): void; (cb: () => (n: number) => number): void; }
>n : number
declare function f(cb: () => (n: number) => number): void;
>f : { (n: number): void; (cb: () => (n: number) => number): void; }
>cb : () => (n: number) => number
>n : number
f(() => n => n);
>f(() => n => n) : void
>f : { (n: number): void; (cb: () => (n: number) => number): void; }
>() => n => n : () => (n: number) => number
>n => n : (n: number) => number
>n : number
>n : number

View file

@ -1,15 +1,15 @@
tests/cases/compiler/contextualTypingWithFixedTypeParameters1.ts(2,22): error TS2339: Property 'foo' does not exist on type 'string'.
tests/cases/compiler/contextualTypingWithFixedTypeParameters1.ts(3,32): error TS2339: Property 'foo' does not exist on type 'string'.
tests/cases/compiler/contextualTypingWithFixedTypeParameters1.ts(3,38): error TS2345: Argument of type '1' is not assignable to parameter of type 'string'.
tests/cases/compiler/contextualTypingWithFixedTypeParameters1.ts(3,32): error TS2339: Property 'foo' does not exist on type '""'.
tests/cases/compiler/contextualTypingWithFixedTypeParameters1.ts(3,38): error TS2345: Argument of type '1' is not assignable to parameter of type '""'.
==== tests/cases/compiler/contextualTypingWithFixedTypeParameters1.ts (3 errors) ====
var f10: <T>(x: T, b: () => (a: T) => void, y: T) => T;
f10('', () => a => a.foo, ''); // a is string
f10('', () => a => a.foo, ''); // a is ""
~~~
!!! error TS2339: Property 'foo' does not exist on type 'string'.
var r9 = f10('', () => (a => a.foo), 1); // error
~~~
!!! error TS2339: Property 'foo' does not exist on type 'string'.
!!! error TS2339: Property 'foo' does not exist on type '""'.
~
!!! error TS2345: Argument of type '1' is not assignable to parameter of type 'string'.
!!! error TS2345: Argument of type '1' is not assignable to parameter of type '""'.

View file

@ -1,9 +1,9 @@
//// [contextualTypingWithFixedTypeParameters1.ts]
var f10: <T>(x: T, b: () => (a: T) => void, y: T) => T;
f10('', () => a => a.foo, ''); // a is string
f10('', () => a => a.foo, ''); // a is ""
var r9 = f10('', () => (a => a.foo), 1); // error
//// [contextualTypingWithFixedTypeParameters1.js]
var f10;
f10('', function () { return function (a) { return a.foo; }; }, ''); // a is string
f10('', function () { return function (a) { return a.foo; }; }, ''); // a is ""
var r9 = f10('', function () { return (function (a) { return a.foo; }); }, 1); // error

View file

@ -1,11 +1,11 @@
interface I {
a(s: string): void;
b(): (n: number) => void;
}
declare function f(i: I): void;
f({
a: s => {},
b: () => n => {},
});
interface I {
a(s: string): void;
b(): (n: number) => void;
}
declare function f(i: I): void;
f({
a: s => {},
b: () => n => {},
});

View file

@ -0,0 +1,4 @@
declare function f(n: number): void;
declare function f(cb: () => (n: number) => number): void;
f(() => n => n);

View file

@ -1,3 +1,3 @@
var f10: <T>(x: T, b: () => (a: T) => void, y: T) => T;
f10('', () => a => a.foo, ''); // a is string
f10('', () => a => a.foo, ''); // a is ""
var r9 = f10('', () => (a => a.foo), 1); // error