diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a5c161abae051..f9350010c2a5e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -21025,7 +21025,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function hasContextSensitiveReturnExpression(node: FunctionLikeDeclaration) { - if (node.typeParameters || getEffectiveReturnTypeNode(node) || !node.body) { + if (getEffectiveReturnTypeNode(node) || !node.body) { return false; } if (node.body.kind !== SyntaxKind.Block) { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index ce3182ddd9d40..2729d846d974e 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -10783,20 +10783,17 @@ export function getContainingNodeArray(node: Node): NodeArray | undefined /** @internal */ export function hasContextSensitiveParameters(node: FunctionLikeDeclaration): boolean { - // Functions with type parameters are not context sensitive. - if (!node.typeParameters) { - // Functions with any parameters that lack type annotations are context sensitive. - if (some(node.parameters, p => !getEffectiveTypeAnnotationNode(p))) { + // Functions with any parameters that lack type annotations are context sensitive. + if (some(node.parameters, p => !getEffectiveTypeAnnotationNode(p))) { + return true; + } + 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 (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; - } - } } return false; } diff --git a/tests/baselines/reference/contextualTypingGenericFunction2.js b/tests/baselines/reference/contextualTypingGenericFunction2.js new file mode 100644 index 0000000000000..5f06aa6fc7b8b --- /dev/null +++ b/tests/baselines/reference/contextualTypingGenericFunction2.js @@ -0,0 +1,89 @@ +//// [tests/cases/compiler/contextualTypingGenericFunction2.ts] //// + +//// [contextualTypingGenericFunction2.ts] +// https://github.com/microsoft/TypeScript/issues/61791 + +declare const fn1: , Ret>( + self: T, + body: (this: T, ...args: Args) => Ret, +) => (...args: Args) => Ret; + +export const ok1 = fn1({ message: "foo" }, function (n: number) { + this.message; +}); + +export const ok2 = fn1({ message: "foo" }, function (n: N) { + this.message; +}); + +declare const fn2: , Ret>( + body: (first: string, ...args: Args) => Ret, +) => (...args: Args) => Ret; + +export const ok3 = fn2(function (first, n: N) {}); + +declare const fn3: , Ret>( + body: (...args: Args) => (arg: string) => Ret, +) => (...args: Args) => Ret; + +export const ok4 = fn3(function (n: N) { + return (arg) => { + return 10 + } +}); + +declare function fn4(config: { + context: T; + callback: (params: P) => (context: T, params: P) => number; +}): (params: P) => number; + +export const ok5 = fn4({ + context: 1, + callback: (params: T) => { + return (a, b) => a + 1; + }, +}); + +declare const fnGen1: , Ret>( + self: T, + body: (this: T, ...args: Args) => Generator, +) => (...args: Args) => Ret; + +export const ok6 = fnGen1({ message: "foo" }, function* (n: number) { + this.message; +}); + +export const ok7 = fnGen1({ message: "foo" }, function* (n: N) { + this.message; +}); + + + + +//// [contextualTypingGenericFunction2.d.ts] +export declare const ok1: (n: number) => void; +export declare const ok2: (n: any) => void; +export declare const ok3: (n: N) => void; +export declare const ok4: (n: N) => number; +export declare const ok5: (params: T) => number; +export declare const ok6: (n: number) => void; +export declare const ok7: (n: any) => void; + + +//// [DtsFileErrors] + + +contextualTypingGenericFunction2.d.ts(5,36): error TS2304: Cannot find name 'T'. + + +==== contextualTypingGenericFunction2.d.ts (1 errors) ==== + export declare const ok1: (n: number) => void; + export declare const ok2: (n: any) => void; + export declare const ok3: (n: N) => void; + export declare const ok4: (n: N) => number; + export declare const ok5: (params: T) => number; + ~ +!!! error TS2304: Cannot find name 'T'. + export declare const ok6: (n: number) => void; + export declare const ok7: (n: any) => void; + \ No newline at end of file diff --git a/tests/baselines/reference/contextualTypingGenericFunction2.symbols b/tests/baselines/reference/contextualTypingGenericFunction2.symbols new file mode 100644 index 0000000000000..16c60357bd75f --- /dev/null +++ b/tests/baselines/reference/contextualTypingGenericFunction2.symbols @@ -0,0 +1,212 @@ +//// [tests/cases/compiler/contextualTypingGenericFunction2.ts] //// + +=== contextualTypingGenericFunction2.ts === +// https://github.com/microsoft/TypeScript/issues/61791 + +declare const fn1: , Ret>( +>fn1 : Symbol(fn1, Decl(contextualTypingGenericFunction2.ts, 2, 13)) +>T : Symbol(T, Decl(contextualTypingGenericFunction2.ts, 2, 20)) +>Args : Symbol(Args, Decl(contextualTypingGenericFunction2.ts, 2, 22)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --) ... and 4 more) +>Ret : Symbol(Ret, Decl(contextualTypingGenericFunction2.ts, 2, 47)) + + self: T, +>self : Symbol(self, Decl(contextualTypingGenericFunction2.ts, 2, 53)) +>T : Symbol(T, Decl(contextualTypingGenericFunction2.ts, 2, 20)) + + body: (this: T, ...args: Args) => Ret, +>body : Symbol(body, Decl(contextualTypingGenericFunction2.ts, 3, 10)) +>this : Symbol(this, Decl(contextualTypingGenericFunction2.ts, 4, 9)) +>T : Symbol(T, Decl(contextualTypingGenericFunction2.ts, 2, 20)) +>args : Symbol(args, Decl(contextualTypingGenericFunction2.ts, 4, 17)) +>Args : Symbol(Args, Decl(contextualTypingGenericFunction2.ts, 2, 22)) +>Ret : Symbol(Ret, Decl(contextualTypingGenericFunction2.ts, 2, 47)) + +) => (...args: Args) => Ret; +>args : Symbol(args, Decl(contextualTypingGenericFunction2.ts, 5, 6)) +>Args : Symbol(Args, Decl(contextualTypingGenericFunction2.ts, 2, 22)) +>Ret : Symbol(Ret, Decl(contextualTypingGenericFunction2.ts, 2, 47)) + +export const ok1 = fn1({ message: "foo" }, function (n: number) { +>ok1 : Symbol(ok1, Decl(contextualTypingGenericFunction2.ts, 7, 12)) +>fn1 : Symbol(fn1, Decl(contextualTypingGenericFunction2.ts, 2, 13)) +>message : Symbol(message, Decl(contextualTypingGenericFunction2.ts, 7, 24)) +>n : Symbol(n, Decl(contextualTypingGenericFunction2.ts, 7, 53)) + + this.message; +>this.message : Symbol(message, Decl(contextualTypingGenericFunction2.ts, 7, 24)) +>this : Symbol(this, Decl(contextualTypingGenericFunction2.ts, 4, 9)) +>message : Symbol(message, Decl(contextualTypingGenericFunction2.ts, 7, 24)) + +}); + +export const ok2 = fn1({ message: "foo" }, function (n: N) { +>ok2 : Symbol(ok2, Decl(contextualTypingGenericFunction2.ts, 11, 12)) +>fn1 : Symbol(fn1, Decl(contextualTypingGenericFunction2.ts, 2, 13)) +>message : Symbol(message, Decl(contextualTypingGenericFunction2.ts, 11, 24)) +>N : Symbol(N, Decl(contextualTypingGenericFunction2.ts, 11, 53)) +>n : Symbol(n, Decl(contextualTypingGenericFunction2.ts, 11, 56)) +>N : Symbol(N, Decl(contextualTypingGenericFunction2.ts, 11, 53)) + + this.message; +>this.message : Symbol(message, Decl(contextualTypingGenericFunction2.ts, 11, 24)) +>this : Symbol(this, Decl(contextualTypingGenericFunction2.ts, 4, 9)) +>message : Symbol(message, Decl(contextualTypingGenericFunction2.ts, 11, 24)) + +}); + +declare const fn2: , Ret>( +>fn2 : Symbol(fn2, Decl(contextualTypingGenericFunction2.ts, 15, 13)) +>Args : Symbol(Args, Decl(contextualTypingGenericFunction2.ts, 15, 20)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --) ... and 4 more) +>Ret : Symbol(Ret, Decl(contextualTypingGenericFunction2.ts, 15, 44)) + + body: (first: string, ...args: Args) => Ret, +>body : Symbol(body, Decl(contextualTypingGenericFunction2.ts, 15, 50)) +>first : Symbol(first, Decl(contextualTypingGenericFunction2.ts, 16, 9)) +>args : Symbol(args, Decl(contextualTypingGenericFunction2.ts, 16, 23)) +>Args : Symbol(Args, Decl(contextualTypingGenericFunction2.ts, 15, 20)) +>Ret : Symbol(Ret, Decl(contextualTypingGenericFunction2.ts, 15, 44)) + +) => (...args: Args) => Ret; +>args : Symbol(args, Decl(contextualTypingGenericFunction2.ts, 17, 6)) +>Args : Symbol(Args, Decl(contextualTypingGenericFunction2.ts, 15, 20)) +>Ret : Symbol(Ret, Decl(contextualTypingGenericFunction2.ts, 15, 44)) + +export const ok3 = fn2(function (first, n: N) {}); +>ok3 : Symbol(ok3, Decl(contextualTypingGenericFunction2.ts, 19, 12)) +>fn2 : Symbol(fn2, Decl(contextualTypingGenericFunction2.ts, 15, 13)) +>N : Symbol(N, Decl(contextualTypingGenericFunction2.ts, 19, 33)) +>first : Symbol(first, Decl(contextualTypingGenericFunction2.ts, 19, 36)) +>n : Symbol(n, Decl(contextualTypingGenericFunction2.ts, 19, 42)) +>N : Symbol(N, Decl(contextualTypingGenericFunction2.ts, 19, 33)) + +declare const fn3: , Ret>( +>fn3 : Symbol(fn3, Decl(contextualTypingGenericFunction2.ts, 21, 13)) +>Args : Symbol(Args, Decl(contextualTypingGenericFunction2.ts, 21, 20)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --) ... and 4 more) +>Ret : Symbol(Ret, Decl(contextualTypingGenericFunction2.ts, 21, 44)) + + body: (...args: Args) => (arg: string) => Ret, +>body : Symbol(body, Decl(contextualTypingGenericFunction2.ts, 21, 50)) +>args : Symbol(args, Decl(contextualTypingGenericFunction2.ts, 22, 9)) +>Args : Symbol(Args, Decl(contextualTypingGenericFunction2.ts, 21, 20)) +>arg : Symbol(arg, Decl(contextualTypingGenericFunction2.ts, 22, 28)) +>Ret : Symbol(Ret, Decl(contextualTypingGenericFunction2.ts, 21, 44)) + +) => (...args: Args) => Ret; +>args : Symbol(args, Decl(contextualTypingGenericFunction2.ts, 23, 6)) +>Args : Symbol(Args, Decl(contextualTypingGenericFunction2.ts, 21, 20)) +>Ret : Symbol(Ret, Decl(contextualTypingGenericFunction2.ts, 21, 44)) + +export const ok4 = fn3(function (n: N) { +>ok4 : Symbol(ok4, Decl(contextualTypingGenericFunction2.ts, 25, 12)) +>fn3 : Symbol(fn3, Decl(contextualTypingGenericFunction2.ts, 21, 13)) +>N : Symbol(N, Decl(contextualTypingGenericFunction2.ts, 25, 33)) +>n : Symbol(n, Decl(contextualTypingGenericFunction2.ts, 25, 36)) +>N : Symbol(N, Decl(contextualTypingGenericFunction2.ts, 25, 33)) + + return (arg) => { +>arg : Symbol(arg, Decl(contextualTypingGenericFunction2.ts, 26, 12)) + + return 10 + } +}); + +declare function fn4(config: { +>fn4 : Symbol(fn4, Decl(contextualTypingGenericFunction2.ts, 29, 3)) +>T : Symbol(T, Decl(contextualTypingGenericFunction2.ts, 31, 21)) +>P : Symbol(P, Decl(contextualTypingGenericFunction2.ts, 31, 23)) +>config : Symbol(config, Decl(contextualTypingGenericFunction2.ts, 31, 27)) + + context: T; +>context : Symbol(context, Decl(contextualTypingGenericFunction2.ts, 31, 36)) +>T : Symbol(T, Decl(contextualTypingGenericFunction2.ts, 31, 21)) + + callback: (params: P) => (context: T, params: P) => number; +>callback : Symbol(callback, Decl(contextualTypingGenericFunction2.ts, 32, 13)) +>params : Symbol(params, Decl(contextualTypingGenericFunction2.ts, 33, 13)) +>P : Symbol(P, Decl(contextualTypingGenericFunction2.ts, 31, 23)) +>context : Symbol(context, Decl(contextualTypingGenericFunction2.ts, 33, 28)) +>T : Symbol(T, Decl(contextualTypingGenericFunction2.ts, 31, 21)) +>params : Symbol(params, Decl(contextualTypingGenericFunction2.ts, 33, 39)) +>P : Symbol(P, Decl(contextualTypingGenericFunction2.ts, 31, 23)) + +}): (params: P) => number; +>params : Symbol(params, Decl(contextualTypingGenericFunction2.ts, 34, 5)) +>P : Symbol(P, Decl(contextualTypingGenericFunction2.ts, 31, 23)) + +export const ok5 = fn4({ +>ok5 : Symbol(ok5, Decl(contextualTypingGenericFunction2.ts, 36, 12)) +>fn4 : Symbol(fn4, Decl(contextualTypingGenericFunction2.ts, 29, 3)) + + context: 1, +>context : Symbol(context, Decl(contextualTypingGenericFunction2.ts, 36, 24)) + + callback: (params: T) => { +>callback : Symbol(callback, Decl(contextualTypingGenericFunction2.ts, 37, 13)) +>T : Symbol(T, Decl(contextualTypingGenericFunction2.ts, 38, 13)) +>params : Symbol(params, Decl(contextualTypingGenericFunction2.ts, 38, 17)) +>T : Symbol(T, Decl(contextualTypingGenericFunction2.ts, 38, 13)) + + return (a, b) => a + 1; +>a : Symbol(a, Decl(contextualTypingGenericFunction2.ts, 39, 12)) +>b : Symbol(b, Decl(contextualTypingGenericFunction2.ts, 39, 14)) +>a : Symbol(a, Decl(contextualTypingGenericFunction2.ts, 39, 12)) + + }, +}); + +declare const fnGen1: , Ret>( +>fnGen1 : Symbol(fnGen1, Decl(contextualTypingGenericFunction2.ts, 43, 13)) +>T : Symbol(T, Decl(contextualTypingGenericFunction2.ts, 43, 23)) +>Args : Symbol(Args, Decl(contextualTypingGenericFunction2.ts, 43, 25)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --) ... and 4 more) +>Ret : Symbol(Ret, Decl(contextualTypingGenericFunction2.ts, 43, 50)) + + self: T, +>self : Symbol(self, Decl(contextualTypingGenericFunction2.ts, 43, 56)) +>T : Symbol(T, Decl(contextualTypingGenericFunction2.ts, 43, 23)) + + body: (this: T, ...args: Args) => Generator, +>body : Symbol(body, Decl(contextualTypingGenericFunction2.ts, 44, 10)) +>this : Symbol(this, Decl(contextualTypingGenericFunction2.ts, 45, 9)) +>T : Symbol(T, Decl(contextualTypingGenericFunction2.ts, 43, 23)) +>args : Symbol(args, Decl(contextualTypingGenericFunction2.ts, 45, 17)) +>Args : Symbol(Args, Decl(contextualTypingGenericFunction2.ts, 43, 25)) +>Generator : Symbol(Generator, Decl(lib.es2015.generator.d.ts, --, --)) +>Ret : Symbol(Ret, Decl(contextualTypingGenericFunction2.ts, 43, 50)) + +) => (...args: Args) => Ret; +>args : Symbol(args, Decl(contextualTypingGenericFunction2.ts, 46, 6)) +>Args : Symbol(Args, Decl(contextualTypingGenericFunction2.ts, 43, 25)) +>Ret : Symbol(Ret, Decl(contextualTypingGenericFunction2.ts, 43, 50)) + +export const ok6 = fnGen1({ message: "foo" }, function* (n: number) { +>ok6 : Symbol(ok6, Decl(contextualTypingGenericFunction2.ts, 48, 12)) +>fnGen1 : Symbol(fnGen1, Decl(contextualTypingGenericFunction2.ts, 43, 13)) +>message : Symbol(message, Decl(contextualTypingGenericFunction2.ts, 48, 27)) +>n : Symbol(n, Decl(contextualTypingGenericFunction2.ts, 48, 57)) + + this.message; +>this.message : Symbol(message, Decl(contextualTypingGenericFunction2.ts, 48, 27)) +>this : Symbol(this, Decl(contextualTypingGenericFunction2.ts, 45, 9)) +>message : Symbol(message, Decl(contextualTypingGenericFunction2.ts, 48, 27)) + +}); + +export const ok7 = fnGen1({ message: "foo" }, function* (n: N) { +>ok7 : Symbol(ok7, Decl(contextualTypingGenericFunction2.ts, 52, 12)) +>fnGen1 : Symbol(fnGen1, Decl(contextualTypingGenericFunction2.ts, 43, 13)) +>message : Symbol(message, Decl(contextualTypingGenericFunction2.ts, 52, 27)) +>N : Symbol(N, Decl(contextualTypingGenericFunction2.ts, 52, 57)) +>n : Symbol(n, Decl(contextualTypingGenericFunction2.ts, 52, 60)) +>N : Symbol(N, Decl(contextualTypingGenericFunction2.ts, 52, 57)) + + this.message; +>this.message : Symbol(message, Decl(contextualTypingGenericFunction2.ts, 52, 27)) +>this : Symbol(this, Decl(contextualTypingGenericFunction2.ts, 45, 9)) +>message : Symbol(message, Decl(contextualTypingGenericFunction2.ts, 52, 27)) + +}); + diff --git a/tests/baselines/reference/contextualTypingGenericFunction2.types b/tests/baselines/reference/contextualTypingGenericFunction2.types new file mode 100644 index 0000000000000..970aef92e6806 --- /dev/null +++ b/tests/baselines/reference/contextualTypingGenericFunction2.types @@ -0,0 +1,296 @@ +//// [tests/cases/compiler/contextualTypingGenericFunction2.ts] //// + +=== Performance Stats === +Type Count: 1,000 +Instantiation count: 2,500 + +=== contextualTypingGenericFunction2.ts === +// https://github.com/microsoft/TypeScript/issues/61791 + +declare const fn1: , Ret>( +>fn1 : , Ret>(self: T, body: (this: T, ...args: Args) => Ret) => (...args: Args) => Ret +> : ^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^^^^ + + self: T, +>self : T +> : ^ + + body: (this: T, ...args: Args) => Ret, +>body : (this: T, ...args: Args) => Ret +> : ^ ^^ ^^^^^ ^^ ^^^^^ +>this : T +> : ^ +>args : Args +> : ^^^^ + +) => (...args: Args) => Ret; +>args : Args +> : ^^^^ + +export const ok1 = fn1({ message: "foo" }, function (n: number) { +>ok1 : (n: number) => void +> : ^^^^^^^^^^^^^^^^^^^ +>fn1({ message: "foo" }, function (n: number) { this.message;}) : (n: number) => void +> : ^^^^^^^^^^^^^^^^^^^ +>fn1 : , Ret>(self: T, body: (this: T, ...args: Args) => Ret) => (...args: Args) => Ret +> : ^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^^^^ +>{ message: "foo" } : { message: string; } +> : ^^^^^^^^^^^^^^^^^^^^ +>message : string +> : ^^^^^^ +>"foo" : "foo" +> : ^^^^^ +>function (n: number) { this.message;} : (this: { message: string; }, n: number) => void +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^ +>n : number +> : ^^^^^^ + + this.message; +>this.message : string +> : ^^^^^^ +>this : { message: string; } +> : ^^^^^^^^^^^^^^^^^^^^ +>message : string +> : ^^^^^^ + +}); + +export const ok2 = fn1({ message: "foo" }, function (n: N) { +>ok2 : (n: any) => void +> : ^^^^^^^^^^^^^^^^ +>fn1({ message: "foo" }, function (n: N) { this.message;}) : (n: any) => void +> : ^^^^^^^^^^^^^^^^ +>fn1 : , Ret>(self: T, body: (this: T, ...args: Args) => Ret) => (...args: Args) => Ret +> : ^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^^^^ +>{ message: "foo" } : { message: string; } +> : ^^^^^^^^^^^^^^^^^^^^ +>message : string +> : ^^^^^^ +>"foo" : "foo" +> : ^^^^^ +>function (n: N) { this.message;} : (this: { message: string; }, n: N) => void +> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^ +>n : N +> : ^ + + this.message; +>this.message : string +> : ^^^^^^ +>this : { message: string; } +> : ^^^^^^^^^^^^^^^^^^^^ +>message : string +> : ^^^^^^ + +}); + +declare const fn2: , Ret>( +>fn2 : , Ret>(body: (first: string, ...args: Args) => Ret) => (...args: Args) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^^^^ + + body: (first: string, ...args: Args) => Ret, +>body : (first: string, ...args: Args) => Ret +> : ^ ^^ ^^^^^ ^^ ^^^^^ +>first : string +> : ^^^^^^ +>args : Args +> : ^^^^ + +) => (...args: Args) => Ret; +>args : Args +> : ^^^^ + +export const ok3 = fn2(function (first, n: N) {}); +>ok3 : (n: N) => void +> : ^ ^^^^^^^^^^^^^^^ +>fn2(function (first, n: N) {}) : (n: N) => void +> : ^ ^^^^^^^^^^^^^^^ +>fn2 : , Ret>(body: (first: string, ...args: Args) => Ret) => (...args: Args) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^^^^ +>function (first, n: N) {} : (first: string, n: N) => void +> : ^ ^^ ^^^^^^^^^^ ^^ ^^^^^^^^^ +>first : string +> : ^^^^^^ +>n : N +> : ^ + +declare const fn3: , Ret>( +>fn3 : , Ret>(body: (...args: Args) => (arg: string) => Ret) => (...args: Args) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^^^^ + + body: (...args: Args) => (arg: string) => Ret, +>body : (...args: Args) => (arg: string) => Ret +> : ^^^^ ^^ ^^^^^ +>args : Args +> : ^^^^ +>arg : string +> : ^^^^^^ + +) => (...args: Args) => Ret; +>args : Args +> : ^^^^ + +export const ok4 = fn3(function (n: N) { +>ok4 : (n: N) => number +> : ^ ^^^^^^^^^^^^^^^^^ +>fn3(function (n: N) { return (arg) => { return 10 }}) : (n: N) => number +> : ^ ^^^^^^^^^^^^^^^^^ +>fn3 : , Ret>(body: (...args: Args) => (arg: string) => Ret) => (...args: Args) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^^^^ +>function (n: N) { return (arg) => { return 10 }} : (n: N) => (arg: string) => number +> : ^ ^^ ^^ ^^^^^^ ^^^^^^^^^^^^^^^^^^^ +>n : N +> : ^ + + return (arg) => { +>(arg) => { return 10 } : (arg: string) => number +> : ^ ^^^^^^^^^^^^^^^^^^^ +>arg : string +> : ^^^^^^ + + return 10 +>10 : 10 +> : ^^ + } +}); + +declare function fn4(config: { +>fn4 : (config: { context: T; callback: (params: P) => (context: T, params: P) => number; }) => (params: P) => number +> : ^ ^^ ^^ ^^ ^^^^^ +>config : { context: T; callback: (params: P) => (context: T, params: P) => number; } +> : ^^^^^^^^^^^ ^^^^^^^^^^^^ ^^^ + + context: T; +>context : T +> : ^ + + callback: (params: P) => (context: T, params: P) => number; +>callback : (params: P) => (context: T, params: P) => number +> : ^ ^^ ^^^^^ +>params : P +> : ^ +>context : T +> : ^ +>params : P +> : ^ + +}): (params: P) => number; +>params : P +> : ^ + +export const ok5 = fn4({ +>ok5 : (params: T) => number +> : ^ ^^^^^^^^ +>fn4({ context: 1, callback: (params: T) => { return (a, b) => a + 1; },}) : (params: T) => number +> : ^ ^^^^^^^^ +>fn4 : (config: { context: T; callback: (params: P) => (context: T, params: P) => number; }) => (params: P) => number +> : ^ ^^ ^^ ^^ ^^^^^ +>{ context: 1, callback: (params: T) => { return (a, b) => a + 1; },} : { context: number; callback: (params: T) => (a: number, b: T) => number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^ + + context: 1, +>context : number +> : ^^^^^^ +>1 : 1 +> : ^ + + callback: (params: T) => { +>callback : (params: T) => (a: number, b: T) => number +> : ^ ^^ ^^ ^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ +>(params: T) => { return (a, b) => a + 1; } : (params: T) => (a: number, b: T) => number +> : ^ ^^ ^^ ^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ +>params : T +> : ^ + + return (a, b) => a + 1; +>(a, b) => a + 1 : (a: number, b: T) => number +> : ^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ +>a : number +> : ^^^^^^ +>b : T +> : ^ +>a + 1 : number +> : ^^^^^^ +>a : number +> : ^^^^^^ +>1 : 1 +> : ^ + + }, +}); + +declare const fnGen1: , Ret>( +>fnGen1 : , Ret>(self: T, body: (this: T, ...args: Args) => Generator) => (...args: Args) => Ret +> : ^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^^^^ + + self: T, +>self : T +> : ^ + + body: (this: T, ...args: Args) => Generator, +>body : (this: T, ...args: Args) => Generator +> : ^ ^^ ^^^^^ ^^ ^^^^^ +>this : T +> : ^ +>args : Args +> : ^^^^ + +) => (...args: Args) => Ret; +>args : Args +> : ^^^^ + +export const ok6 = fnGen1({ message: "foo" }, function* (n: number) { +>ok6 : (n: number) => void +> : ^^^^^^^^^^^^^^^^^^^ +>fnGen1({ message: "foo" }, function* (n: number) { this.message;}) : (n: number) => void +> : ^^^^^^^^^^^^^^^^^^^ +>fnGen1 : , Ret>(self: T, body: (this: T, ...args: Args) => Generator) => (...args: Args) => Ret +> : ^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^^^^ +>{ message: "foo" } : { message: string; } +> : ^^^^^^^^^^^^^^^^^^^^ +>message : string +> : ^^^^^^ +>"foo" : "foo" +> : ^^^^^ +>function* (n: number) { this.message;} : (this: { message: string; }, n: number) => Generator +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>n : number +> : ^^^^^^ + + this.message; +>this.message : string +> : ^^^^^^ +>this : { message: string; } +> : ^^^^^^^^^^^^^^^^^^^^ +>message : string +> : ^^^^^^ + +}); + +export const ok7 = fnGen1({ message: "foo" }, function* (n: N) { +>ok7 : (n: any) => void +> : ^^^^^^^^^^^^^^^^ +>fnGen1({ message: "foo" }, function* (n: N) { this.message;}) : (n: any) => void +> : ^^^^^^^^^^^^^^^^ +>fnGen1 : , Ret>(self: T, body: (this: T, ...args: Args) => Generator) => (...args: Args) => Ret +> : ^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^^^^ +>{ message: "foo" } : { message: string; } +> : ^^^^^^^^^^^^^^^^^^^^ +>message : string +> : ^^^^^^ +>"foo" : "foo" +> : ^^^^^ +>function* (n: N) { this.message;} : (this: { message: string; }, n: N) => Generator +> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>n : N +> : ^ + + this.message; +>this.message : string +> : ^^^^^^ +>this : { message: string; } +> : ^^^^^^^^^^^^^^^^^^^^ +>message : string +> : ^^^^^^ + +}); + diff --git a/tests/cases/compiler/contextualTypingGenericFunction2.ts b/tests/cases/compiler/contextualTypingGenericFunction2.ts new file mode 100644 index 0000000000000..13a4e42c9baeb --- /dev/null +++ b/tests/cases/compiler/contextualTypingGenericFunction2.ts @@ -0,0 +1,60 @@ +// @strict: true +// @target: esnext +// @declaration: true +// @emitDeclarationOnly: true + +// https://github.com/microsoft/TypeScript/issues/61791 + +declare const fn1: , Ret>( + self: T, + body: (this: T, ...args: Args) => Ret, +) => (...args: Args) => Ret; + +export const ok1 = fn1({ message: "foo" }, function (n: number) { + this.message; +}); + +export const ok2 = fn1({ message: "foo" }, function (n: N) { + this.message; +}); + +declare const fn2: , Ret>( + body: (first: string, ...args: Args) => Ret, +) => (...args: Args) => Ret; + +export const ok3 = fn2(function (first, n: N) {}); + +declare const fn3: , Ret>( + body: (...args: Args) => (arg: string) => Ret, +) => (...args: Args) => Ret; + +export const ok4 = fn3(function (n: N) { + return (arg) => { + return 10 + } +}); + +declare function fn4(config: { + context: T; + callback: (params: P) => (context: T, params: P) => number; +}): (params: P) => number; + +export const ok5 = fn4({ + context: 1, + callback: (params: T) => { + return (a, b) => a + 1; + }, +}); + +declare const fnGen1: , Ret>( + self: T, + body: (this: T, ...args: Args) => Generator, +) => (...args: Args) => Ret; + +export const ok6 = fnGen1({ message: "foo" }, function* (n: number) { + this.message; +}); + +export const ok7 = fnGen1({ message: "foo" }, function* (n: N) { + this.message; +}); diff --git a/tests/cases/fourslash/contextualTypingGenericFunction1.ts b/tests/cases/fourslash/contextualTypingGenericFunction1.ts index 9fa6b92da237a..31411f72609c9 100644 --- a/tests/cases/fourslash/contextualTypingGenericFunction1.ts +++ b/tests/cases/fourslash/contextualTypingGenericFunction1.ts @@ -1,6 +1,5 @@ /// -// should not contextually type the RHS because it introduces type parameters ////var obj: { f(x: T): T } = { f: (/*1*/x) => x }; ////var obj2: (x: T) => T = (/*2*/x) => x; //// @@ -11,7 +10,7 @@ ////c.obj = (/*3*/x) => x; verify.quickInfos({ - 1: "(parameter) x: any", - 2: "(parameter) x: any", - 3: "(parameter) x: any" + 1: "(parameter) x: T", + 2: "(parameter) x: T", + 3: "(parameter) x: T" });