diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ba8ec48a39eff..a7e7319f8e59a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -26067,7 +26067,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { }); } - function applyToParameterTypes(source: Signature, target: Signature, callback: (s: Type, t: Type) => void) { + function applyToParameterTypes(source: Signature, target: Signature, callback: (s: Type, t: Type) => void, skipUnannotatedParameters = false) { + const sourceDeclaredCount = source.parameters.length - (signatureHasRestParameter(source) ? 1 : 0); const sourceCount = getParameterCount(source); const targetCount = getParameterCount(target); const sourceRestType = getEffectiveRestType(source); @@ -26082,6 +26083,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } for (let i = 0; i < paramCount; i++) { + if (skipUnannotatedParameters) { + const decl = i < sourceDeclaredCount ? source.parameters[i] : signatureHasRestParameter(source) ? source.parameters[sourceDeclaredCount] : undefined; + if (decl?.valueDeclaration && !getEffectiveTypeAnnotationNode(decl.valueDeclaration)) { + continue + } + } callback(getTypeAtPosition(source, i), getTypeAtPosition(target, i)); } if (targetRestType) { @@ -41376,7 +41383,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const inferences = map(context.inferences, info => createInferenceInfo(info.typeParameter)); applyToParameterTypes(instantiatedSignature, contextualSignature, (source, target) => { inferTypes(inferences, source, target, /*priority*/ 0, /*contravariant*/ true); - }); + }, /*skipUnannotatedParameters*/ true); if (some(inferences, hasInferenceCandidates)) { // We have inference candidates, indicating that one or more type parameters are referenced // in the parameter types of the contextual signature. Now also infer from the return type. @@ -41389,6 +41396,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!hasOverlappingInferences(context.inferences, inferences)) { mergeInferences(context.inferences, inferences); context.inferredTypeParameters = concatenate(context.inferredTypeParameters, uniqueTypeParameters); + assignContextualParameterTypes(signature, instantiateSignature(contextualSignature, context.mapper)); return getOrCreateTypeFromSignature(instantiatedSignature); } } @@ -41812,7 +41820,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // or if its FunctionBody is strict code(11.1.5). checkGrammarModifiers(node); - checkVariableLikeDeclaration(node); + if (getEffectiveTypeAnnotationNode(node)) { + // checking annotated parameters early allows the compiler to find circularties early + checkVariableLikeDeclaration(node); + } else { + // defer resolving the type of unannotated parameters so that late contextual parameter types can be assigned before it + checkNodeDeferred(node); + } const func = getContainingFunction(node)!; if (hasSyntacticModifier(node, ModifierFlags.ParameterPropertyModifier)) { if (compilerOptions.erasableSyntaxOnly) { @@ -49158,6 +49172,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.ClassExpression: checkClassExpressionDeferred(node as ClassExpression); break; + case SyntaxKind.Parameter: + checkVariableLikeDeclaration(node as ParameterDeclaration); + break; case SyntaxKind.TypeParameter: checkTypeParameterDeferred(node as TypeParameterDeclaration); break; diff --git a/tests/baselines/reference/contextualTypingGenericFunction2.errors.txt b/tests/baselines/reference/contextualTypingGenericFunction2.errors.txt new file mode 100644 index 0000000000000..fcacb3c60dfc5 --- /dev/null +++ b/tests/baselines/reference/contextualTypingGenericFunction2.errors.txt @@ -0,0 +1,62 @@ +contextualTypingGenericFunction2.ts(40,22): error TS18046: 'a' is of type 'unknown'. + + +==== contextualTypingGenericFunction2.ts (1 errors) ==== + // 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; + ~ +!!! error TS18046: 'a' is of type 'unknown'. + }, + }); + + 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; + }); + \ No newline at end of file diff --git a/tests/baselines/reference/contextualTypingGenericFunction2.js b/tests/baselines/reference/contextualTypingGenericFunction2.js new file mode 100644 index 0000000000000..712b4155fae22 --- /dev/null +++ b/tests/baselines/reference/contextualTypingGenericFunction2.js @@ -0,0 +1,70 @@ +//// [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: N) => 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: N) => void; 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..6ec974c024a79 --- /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: N) => void +> : ^ ^^^^^^^^^^^^^^^ +>fn1({ message: "foo" }, function (n: N) { this.message;}) : (n: N) => 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: unknown, b: unknown) => any; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ + + context: 1, +>context : number +> : ^^^^^^ +>1 : 1 +> : ^ + + callback: (params: T) => { +>callback : (params: T) => (a: unknown, b: unknown) => any +> : ^ ^^ ^^ ^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^ +>(params: T) => { return (a, b) => a + 1; } : (params: T) => (a: unknown, b: unknown) => any +> : ^ ^^ ^^ ^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^ +>params : T +> : ^ + + return (a, b) => a + 1; +>(a, b) => a + 1 : (a: unknown, b: unknown) => any +> : ^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^ +>a : unknown +> : ^^^^^^^ +>b : unknown +> : ^^^^^^^ +>a + 1 : any +> : ^^^ +>a : unknown +> : ^^^^^^^ +>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: N) => void +> : ^ ^^^^^^^^^^^^^^^ +>fnGen1({ message: "foo" }, function* (n: N) { this.message;}) : (n: N) => 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/baselines/reference/literalTypes2.types b/tests/baselines/reference/literalTypes2.types index 2744be4c5f10b..8190a61a91afd 100644 --- a/tests/baselines/reference/literalTypes2.types +++ b/tests/baselines/reference/literalTypes2.types @@ -375,9 +375,9 @@ function f3() { > : ^^^^^ const c3 = cond ? E.A : cond ? true : 123; ->c3 : true | E.A | 123 +>c3 : true | 123 | E.A > : ^^^^^^^^^^^^^^^^ ->cond ? E.A : cond ? true : 123 : true | E.A | 123 +>cond ? E.A : cond ? true : 123 : true | 123 | E.A > : ^^^^^^^^^^^^^^^^ >cond : boolean > : ^^^^^^^ @@ -473,7 +473,7 @@ function f3() { let x3 = c3; >x3 : number | boolean > : ^^^^^^^^^^^^^^^^ ->c3 : true | E.A | 123 +>c3 : true | 123 | E.A > : ^^^^^^^^^^^^^^^^ let x4 = c4; 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; +});