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:
parent
4c824505ad
commit
fe3a05e89a
|
@ -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 {
|
||||
|
|
|
@ -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; }; });
|
|
@ -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))
|
||||
|
|
@ -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
|
||||
|
|
@ -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 '""'.
|
|
@ -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
|
||||
|
|
|
@ -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 => {},
|
||||
});
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
declare function f(n: number): void;
|
||||
declare function f(cb: () => (n: number) => number): void;
|
||||
|
||||
f(() => n => n);
|
|
@ -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
|
Loading…
Reference in a new issue