diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ba8ec48a39eff..3a52516c3491d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -21088,7 +21088,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) { @@ -38452,6 +38452,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function inferFromAnnotatedParametersAndReturn(signature: Signature, context: Signature, inferenceContext: InferenceContext) { + if (inferenceContext.flags & InferenceFlags.IgnoreAnnotatedParametersAndReturns) { + return; + } const len = signature.parameters.length - (signatureHasRestParameter(signature) ? 1 : 0); for (let i = 0; i < len; i++) { const declaration = signature.parameters[i].valueDeclaration as ParameterDeclaration; @@ -39460,9 +39463,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!signature) { return; } + let saveInferenceFlags: InferenceFlags = InferenceFlags.None; + const inferenceContext = getInferenceContext(node); + if (inferenceContext) { + saveInferenceFlags = inferenceContext.flags; + // inferring from those could possibly infer inner type parameters into outer inference context + // and they could potentially leak in the final inferred type as `instantiateTypeWithSingleGenericCallSignature` + // can only "hoist" them using `context.inferredTypeParameters` in a narrow set of cases + inferenceContext.flags |= node.typeParameters ? InferenceFlags.IgnoreAnnotatedParametersAndReturns : InferenceFlags.None; + } if (isContextSensitive(node)) { if (contextualSignature) { - const inferenceContext = getInferenceContext(node); let instantiatedContextualSignature: Signature | undefined; if (checkMode && checkMode & CheckMode.Inferential) { inferFromAnnotatedParametersAndReturn(signature, contextualSignature, inferenceContext!); @@ -39481,7 +39492,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } else if (contextualSignature && !node.typeParameters && contextualSignature.parameters.length > node.parameters.length) { - const inferenceContext = getInferenceContext(node); if (checkMode && checkMode & CheckMode.Inferential) { inferFromAnnotatedParametersAndReturn(signature, contextualSignature, inferenceContext!); } @@ -39492,6 +39502,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { signature.resolvedReturnType = returnType; } } + if (inferenceContext) { + inferenceContext.flags = saveInferenceFlags; + } checkSignatureDeclaration(node); } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index ee7f4338a3a10..9669a86b77ce9 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -7129,6 +7129,7 @@ export const enum InferenceFlags { NoDefault = 1 << 0, // Infer silentNeverType for no inferences (otherwise anyType or unknownType) AnyDefault = 1 << 1, // Infer anyType (in JS files) for no inferences (otherwise unknownType) SkippedGenericFunction = 1 << 2, // A generic function was skipped during inference + IgnoreAnnotatedParametersAndReturns = 1 << 3, // used when assigning contextual parameters types within generic functions } /** diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index f5b785dc5db8f..7a49ea2f842e5 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -10814,20 +10814,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.errors.txt b/tests/baselines/reference/contextualTypingGenericFunction2.errors.txt new file mode 100644 index 0000000000000..36324c987475c --- /dev/null +++ b/tests/baselines/reference/contextualTypingGenericFunction2.errors.txt @@ -0,0 +1,98 @@ +contextualTypingGenericFunction2.ts(55,3): error TS2322: Type 'number' is not assignable to type 'boolean'. +contextualTypingGenericFunction2.ts(65,3): error TS2322: Type '(params: N) => (a: number, b: unknown) => boolean' is not assignable to type '(params: unknown) => (context: number, params: unknown) => number'. + Call signature return types '(a: number, b: unknown) => boolean' and '(context: number, params: unknown) => number' are incompatible. + Type 'boolean' is not assignable to type 'number'. + + +==== contextualTypingGenericFunction2.ts (2 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 result1 = fn1({ message: "foo" }, function (n: number) { + this.message; + }); + + export const result2 = fn1({ message: "foo" }, function (n: N) { + this.message; + }); + + declare const fn2: , Ret>( + body: (first: string, ...args: Args) => Ret, + ) => (...args: Args) => Ret; + + export const result3 = fn2(function (first, n: N) {}); + + declare const fn3: , Ret>( + body: (...args: Args) => (arg: string) => Ret, + ) => (...args: Args) => Ret; + + export const result4 = fn3(function (n: N) { + return (arg) => { + return 10 + } + }); + + declare function fn4(config: { + context: T; + callback: (params: P) => (context: T, params: P) => number; + other?: (arg: string) => void; + }): (params: P) => number; + + export const result5 = fn4({ + context: 1, + callback: (params: N) => { + return (a, b) => a + 1; + }, + }); + + export const result6 = fn4({ + context: 1, + callback: (params: N) => { + return (a, b) => a + 1; + }, + other: (_) => {} // outer context-sensitive function + }); + + // should error + export const result7 = fn4({ + context: 1, + ~~~~~~~ +!!! error TS2322: Type 'number' is not assignable to type 'boolean'. +!!! related TS6500 contextualTypingGenericFunction2.ts:33:3: The expected type comes from property 'context' which is declared here on type '{ context: boolean; callback: (params: unknown) => (context: boolean, params: unknown) => number; other?: ((arg: string) => void) | undefined; }' + callback: (params: N) => { + return (a: boolean, b) => a ? 1 : 2; + }, + other: (_) => {} // outer context-sensitive function + }); + + // should error + export const result8 = fn4({ + context: 1, + callback: (params: N) => { + ~~~~~~~~ +!!! error TS2322: Type '(params: N) => (a: number, b: unknown) => boolean' is not assignable to type '(params: unknown) => (context: number, params: unknown) => number'. +!!! error TS2322: Call signature return types '(a: number, b: unknown) => boolean' and '(context: number, params: unknown) => number' are incompatible. +!!! error TS2322: Type 'boolean' is not assignable to type 'number'. +!!! related TS6500 contextualTypingGenericFunction2.ts:34:3: The expected type comes from property 'callback' which is declared here on type '{ context: number; callback: (params: unknown) => (context: number, params: unknown) => number; other?: ((arg: string) => void) | undefined; }' + return (a, b) => true; + }, + other: (_) => {} // outer context-sensitive function + }); + + declare const fnGen1: , Ret>( + self: T, + body: (this: T, ...args: Args) => Generator, + ) => (...args: Args) => Ret; + + export const result9 = fnGen1({ message: "foo" }, function* (n: number) { + this.message; + }); + + export const result10 = 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..37c91b01118cc --- /dev/null +++ b/tests/baselines/reference/contextualTypingGenericFunction2.js @@ -0,0 +1,100 @@ +//// [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 result1 = fn1({ message: "foo" }, function (n: number) { + this.message; +}); + +export const result2 = fn1({ message: "foo" }, function (n: N) { + this.message; +}); + +declare const fn2: , Ret>( + body: (first: string, ...args: Args) => Ret, +) => (...args: Args) => Ret; + +export const result3 = fn2(function (first, n: N) {}); + +declare const fn3: , Ret>( + body: (...args: Args) => (arg: string) => Ret, +) => (...args: Args) => Ret; + +export const result4 = fn3(function (n: N) { + return (arg) => { + return 10 + } +}); + +declare function fn4(config: { + context: T; + callback: (params: P) => (context: T, params: P) => number; + other?: (arg: string) => void; +}): (params: P) => number; + +export const result5 = fn4({ + context: 1, + callback: (params: N) => { + return (a, b) => a + 1; + }, +}); + +export const result6 = fn4({ + context: 1, + callback: (params: N) => { + return (a, b) => a + 1; + }, + other: (_) => {} // outer context-sensitive function +}); + +// should error +export const result7 = fn4({ + context: 1, + callback: (params: N) => { + return (a: boolean, b) => a ? 1 : 2; + }, + other: (_) => {} // outer context-sensitive function +}); + + // should error +export const result8 = fn4({ + context: 1, + callback: (params: N) => { + return (a, b) => true; + }, + other: (_) => {} // outer context-sensitive function +}); + +declare const fnGen1: , Ret>( + self: T, + body: (this: T, ...args: Args) => Generator, +) => (...args: Args) => Ret; + +export const result9 = fnGen1({ message: "foo" }, function* (n: number) { + this.message; +}); + +export const result10 = fnGen1({ message: "foo" }, function* (n: N) { + this.message; +}); + + + + +//// [contextualTypingGenericFunction2.d.ts] +export declare const result1: (n: number) => void; +export declare const result2: (n: any) => void; +export declare const result3: (n: N) => void; +export declare const result4: (n: N) => number; +export declare const result5: (params: unknown) => number; +export declare const result6: (params: unknown) => number; +export declare const result7: (params: unknown) => number; +export declare const result8: (params: unknown) => number; +export declare const result9: (n: number) => void; +export declare const result10: (n: any) => void; diff --git a/tests/baselines/reference/contextualTypingGenericFunction2.symbols b/tests/baselines/reference/contextualTypingGenericFunction2.symbols new file mode 100644 index 0000000000000..278d61d327d08 --- /dev/null +++ b/tests/baselines/reference/contextualTypingGenericFunction2.symbols @@ -0,0 +1,292 @@ +//// [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 result1 = fn1({ message: "foo" }, function (n: number) { +>result1 : Symbol(result1, Decl(contextualTypingGenericFunction2.ts, 7, 12)) +>fn1 : Symbol(fn1, Decl(contextualTypingGenericFunction2.ts, 2, 13)) +>message : Symbol(message, Decl(contextualTypingGenericFunction2.ts, 7, 28)) +>n : Symbol(n, Decl(contextualTypingGenericFunction2.ts, 7, 57)) + + this.message; +>this.message : Symbol(message, Decl(contextualTypingGenericFunction2.ts, 7, 28)) +>this : Symbol(this, Decl(contextualTypingGenericFunction2.ts, 4, 9)) +>message : Symbol(message, Decl(contextualTypingGenericFunction2.ts, 7, 28)) + +}); + +export const result2 = fn1({ message: "foo" }, function (n: N) { +>result2 : Symbol(result2, Decl(contextualTypingGenericFunction2.ts, 11, 12)) +>fn1 : Symbol(fn1, Decl(contextualTypingGenericFunction2.ts, 2, 13)) +>message : Symbol(message, Decl(contextualTypingGenericFunction2.ts, 11, 28)) +>N : Symbol(N, Decl(contextualTypingGenericFunction2.ts, 11, 57)) +>n : Symbol(n, Decl(contextualTypingGenericFunction2.ts, 11, 60)) +>N : Symbol(N, Decl(contextualTypingGenericFunction2.ts, 11, 57)) + + this.message; +>this.message : Symbol(message, Decl(contextualTypingGenericFunction2.ts, 11, 28)) +>this : Symbol(this, Decl(contextualTypingGenericFunction2.ts, 4, 9)) +>message : Symbol(message, Decl(contextualTypingGenericFunction2.ts, 11, 28)) + +}); + +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 result3 = fn2(function (first, n: N) {}); +>result3 : Symbol(result3, Decl(contextualTypingGenericFunction2.ts, 19, 12)) +>fn2 : Symbol(fn2, Decl(contextualTypingGenericFunction2.ts, 15, 13)) +>N : Symbol(N, Decl(contextualTypingGenericFunction2.ts, 19, 37)) +>first : Symbol(first, Decl(contextualTypingGenericFunction2.ts, 19, 40)) +>n : Symbol(n, Decl(contextualTypingGenericFunction2.ts, 19, 46)) +>N : Symbol(N, Decl(contextualTypingGenericFunction2.ts, 19, 37)) + +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 result4 = fn3(function (n: N) { +>result4 : Symbol(result4, Decl(contextualTypingGenericFunction2.ts, 25, 12)) +>fn3 : Symbol(fn3, Decl(contextualTypingGenericFunction2.ts, 21, 13)) +>N : Symbol(N, Decl(contextualTypingGenericFunction2.ts, 25, 37)) +>n : Symbol(n, Decl(contextualTypingGenericFunction2.ts, 25, 40)) +>N : Symbol(N, Decl(contextualTypingGenericFunction2.ts, 25, 37)) + + 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)) + + other?: (arg: string) => void; +>other : Symbol(other, Decl(contextualTypingGenericFunction2.ts, 33, 61)) +>arg : Symbol(arg, Decl(contextualTypingGenericFunction2.ts, 34, 11)) + +}): (params: P) => number; +>params : Symbol(params, Decl(contextualTypingGenericFunction2.ts, 35, 5)) +>P : Symbol(P, Decl(contextualTypingGenericFunction2.ts, 31, 23)) + +export const result5 = fn4({ +>result5 : Symbol(result5, Decl(contextualTypingGenericFunction2.ts, 37, 12)) +>fn4 : Symbol(fn4, Decl(contextualTypingGenericFunction2.ts, 29, 3)) + + context: 1, +>context : Symbol(context, Decl(contextualTypingGenericFunction2.ts, 37, 28)) + + callback: (params: N) => { +>callback : Symbol(callback, Decl(contextualTypingGenericFunction2.ts, 38, 13)) +>N : Symbol(N, Decl(contextualTypingGenericFunction2.ts, 39, 13)) +>params : Symbol(params, Decl(contextualTypingGenericFunction2.ts, 39, 17)) +>N : Symbol(N, Decl(contextualTypingGenericFunction2.ts, 39, 13)) + + return (a, b) => a + 1; +>a : Symbol(a, Decl(contextualTypingGenericFunction2.ts, 40, 12)) +>b : Symbol(b, Decl(contextualTypingGenericFunction2.ts, 40, 14)) +>a : Symbol(a, Decl(contextualTypingGenericFunction2.ts, 40, 12)) + + }, +}); + +export const result6 = fn4({ +>result6 : Symbol(result6, Decl(contextualTypingGenericFunction2.ts, 44, 12)) +>fn4 : Symbol(fn4, Decl(contextualTypingGenericFunction2.ts, 29, 3)) + + context: 1, +>context : Symbol(context, Decl(contextualTypingGenericFunction2.ts, 44, 28)) + + callback: (params: N) => { +>callback : Symbol(callback, Decl(contextualTypingGenericFunction2.ts, 45, 13)) +>N : Symbol(N, Decl(contextualTypingGenericFunction2.ts, 46, 13)) +>params : Symbol(params, Decl(contextualTypingGenericFunction2.ts, 46, 17)) +>N : Symbol(N, Decl(contextualTypingGenericFunction2.ts, 46, 13)) + + return (a, b) => a + 1; +>a : Symbol(a, Decl(contextualTypingGenericFunction2.ts, 47, 12)) +>b : Symbol(b, Decl(contextualTypingGenericFunction2.ts, 47, 14)) +>a : Symbol(a, Decl(contextualTypingGenericFunction2.ts, 47, 12)) + + }, + other: (_) => {} // outer context-sensitive function +>other : Symbol(other, Decl(contextualTypingGenericFunction2.ts, 48, 4)) +>_ : Symbol(_, Decl(contextualTypingGenericFunction2.ts, 49, 10)) + +}); + +// should error +export const result7 = fn4({ +>result7 : Symbol(result7, Decl(contextualTypingGenericFunction2.ts, 53, 12)) +>fn4 : Symbol(fn4, Decl(contextualTypingGenericFunction2.ts, 29, 3)) + + context: 1, +>context : Symbol(context, Decl(contextualTypingGenericFunction2.ts, 53, 28)) + + callback: (params: N) => { +>callback : Symbol(callback, Decl(contextualTypingGenericFunction2.ts, 54, 13)) +>N : Symbol(N, Decl(contextualTypingGenericFunction2.ts, 55, 13)) +>params : Symbol(params, Decl(contextualTypingGenericFunction2.ts, 55, 17)) +>N : Symbol(N, Decl(contextualTypingGenericFunction2.ts, 55, 13)) + + return (a: boolean, b) => a ? 1 : 2; +>a : Symbol(a, Decl(contextualTypingGenericFunction2.ts, 56, 12)) +>b : Symbol(b, Decl(contextualTypingGenericFunction2.ts, 56, 23)) +>a : Symbol(a, Decl(contextualTypingGenericFunction2.ts, 56, 12)) + + }, + other: (_) => {} // outer context-sensitive function +>other : Symbol(other, Decl(contextualTypingGenericFunction2.ts, 57, 4)) +>_ : Symbol(_, Decl(contextualTypingGenericFunction2.ts, 58, 10)) + +}); + + // should error +export const result8 = fn4({ +>result8 : Symbol(result8, Decl(contextualTypingGenericFunction2.ts, 62, 12)) +>fn4 : Symbol(fn4, Decl(contextualTypingGenericFunction2.ts, 29, 3)) + + context: 1, +>context : Symbol(context, Decl(contextualTypingGenericFunction2.ts, 62, 28)) + + callback: (params: N) => { +>callback : Symbol(callback, Decl(contextualTypingGenericFunction2.ts, 63, 13)) +>N : Symbol(N, Decl(contextualTypingGenericFunction2.ts, 64, 13)) +>params : Symbol(params, Decl(contextualTypingGenericFunction2.ts, 64, 17)) +>N : Symbol(N, Decl(contextualTypingGenericFunction2.ts, 64, 13)) + + return (a, b) => true; +>a : Symbol(a, Decl(contextualTypingGenericFunction2.ts, 65, 12)) +>b : Symbol(b, Decl(contextualTypingGenericFunction2.ts, 65, 14)) + + }, + other: (_) => {} // outer context-sensitive function +>other : Symbol(other, Decl(contextualTypingGenericFunction2.ts, 66, 4)) +>_ : Symbol(_, Decl(contextualTypingGenericFunction2.ts, 67, 10)) + +}); + +declare const fnGen1: , Ret>( +>fnGen1 : Symbol(fnGen1, Decl(contextualTypingGenericFunction2.ts, 70, 13)) +>T : Symbol(T, Decl(contextualTypingGenericFunction2.ts, 70, 23)) +>Args : Symbol(Args, Decl(contextualTypingGenericFunction2.ts, 70, 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, 70, 50)) + + self: T, +>self : Symbol(self, Decl(contextualTypingGenericFunction2.ts, 70, 56)) +>T : Symbol(T, Decl(contextualTypingGenericFunction2.ts, 70, 23)) + + body: (this: T, ...args: Args) => Generator, +>body : Symbol(body, Decl(contextualTypingGenericFunction2.ts, 71, 10)) +>this : Symbol(this, Decl(contextualTypingGenericFunction2.ts, 72, 9)) +>T : Symbol(T, Decl(contextualTypingGenericFunction2.ts, 70, 23)) +>args : Symbol(args, Decl(contextualTypingGenericFunction2.ts, 72, 17)) +>Args : Symbol(Args, Decl(contextualTypingGenericFunction2.ts, 70, 25)) +>Generator : Symbol(Generator, Decl(lib.es2015.generator.d.ts, --, --)) +>Ret : Symbol(Ret, Decl(contextualTypingGenericFunction2.ts, 70, 50)) + +) => (...args: Args) => Ret; +>args : Symbol(args, Decl(contextualTypingGenericFunction2.ts, 73, 6)) +>Args : Symbol(Args, Decl(contextualTypingGenericFunction2.ts, 70, 25)) +>Ret : Symbol(Ret, Decl(contextualTypingGenericFunction2.ts, 70, 50)) + +export const result9 = fnGen1({ message: "foo" }, function* (n: number) { +>result9 : Symbol(result9, Decl(contextualTypingGenericFunction2.ts, 75, 12)) +>fnGen1 : Symbol(fnGen1, Decl(contextualTypingGenericFunction2.ts, 70, 13)) +>message : Symbol(message, Decl(contextualTypingGenericFunction2.ts, 75, 31)) +>n : Symbol(n, Decl(contextualTypingGenericFunction2.ts, 75, 61)) + + this.message; +>this.message : Symbol(message, Decl(contextualTypingGenericFunction2.ts, 75, 31)) +>this : Symbol(this, Decl(contextualTypingGenericFunction2.ts, 72, 9)) +>message : Symbol(message, Decl(contextualTypingGenericFunction2.ts, 75, 31)) + +}); + +export const result10 = fnGen1({ message: "foo" }, function* (n: N) { +>result10 : Symbol(result10, Decl(contextualTypingGenericFunction2.ts, 79, 12)) +>fnGen1 : Symbol(fnGen1, Decl(contextualTypingGenericFunction2.ts, 70, 13)) +>message : Symbol(message, Decl(contextualTypingGenericFunction2.ts, 79, 32)) +>N : Symbol(N, Decl(contextualTypingGenericFunction2.ts, 79, 62)) +>n : Symbol(n, Decl(contextualTypingGenericFunction2.ts, 79, 65)) +>N : Symbol(N, Decl(contextualTypingGenericFunction2.ts, 79, 62)) + + this.message; +>this.message : Symbol(message, Decl(contextualTypingGenericFunction2.ts, 79, 32)) +>this : Symbol(this, Decl(contextualTypingGenericFunction2.ts, 72, 9)) +>message : Symbol(message, Decl(contextualTypingGenericFunction2.ts, 79, 32)) + +}); + diff --git a/tests/baselines/reference/contextualTypingGenericFunction2.types b/tests/baselines/reference/contextualTypingGenericFunction2.types new file mode 100644 index 0000000000000..2d2d10f40bd49 --- /dev/null +++ b/tests/baselines/reference/contextualTypingGenericFunction2.types @@ -0,0 +1,449 @@ +//// [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 result1 = fn1({ message: "foo" }, function (n: number) { +>result1 : (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 result2 = fn1({ message: "foo" }, function (n: N) { +>result2 : (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 result3 = fn2(function (first, n: N) {}); +>result3 : (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 result4 = fn3(function (n: N) { +>result4 : (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; other?: (arg: string) => void; }) => (params: P) => number +> : ^ ^^ ^^ ^^ ^^^^^ +>config : { context: T; callback: (params: P) => (context: T, params: P) => number; other?: (arg: string) => void; } +> : ^^^^^^^^^^^ ^^^^^^^^^^^^ ^^^^^^^^^^ ^^^ + + 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 +> : ^ + + other?: (arg: string) => void; +>other : ((arg: string) => void) | undefined +> : ^^ ^^ ^^^^^ ^^^^^^^^^^^^^ +>arg : string +> : ^^^^^^ + +}): (params: P) => number; +>params : P +> : ^ + +export const result5 = fn4({ +>result5 : (params: unknown) => number +> : ^ ^^^^^^^^^^^^^^ +>fn4({ context: 1, callback: (params: N) => { return (a, b) => a + 1; },}) : (params: unknown) => number +> : ^ ^^^^^^^^^^^^^^ +>fn4 : (config: { context: T; callback: (params: P) => (context: T, params: P) => number; other?: (arg: string) => void; }) => (params: P) => number +> : ^ ^^ ^^ ^^ ^^^^^ +>{ context: 1, callback: (params: N) => { return (a, b) => a + 1; },} : { context: number; callback: (params: N) => (a: number, b: unknown) => number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^ + + context: 1, +>context : number +> : ^^^^^^ +>1 : 1 +> : ^ + + callback: (params: N) => { +>callback : (params: N) => (a: number, b: unknown) => number +> : ^ ^^ ^^ ^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ +>(params: N) => { return (a, b) => a + 1; } : (params: N) => (a: number, b: unknown) => number +> : ^ ^^ ^^ ^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ +>params : N +> : ^ + + return (a, b) => a + 1; +>(a, b) => a + 1 : (a: number, b: unknown) => number +> : ^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ +>a : number +> : ^^^^^^ +>b : unknown +> : ^^^^^^^ +>a + 1 : number +> : ^^^^^^ +>a : number +> : ^^^^^^ +>1 : 1 +> : ^ + + }, +}); + +export const result6 = fn4({ +>result6 : (params: unknown) => number +> : ^ ^^^^^^^^^^^^^^ +>fn4({ context: 1, callback: (params: N) => { return (a, b) => a + 1; }, other: (_) => {} // outer context-sensitive function}) : (params: unknown) => number +> : ^ ^^^^^^^^^^^^^^ +>fn4 : (config: { context: T; callback: (params: P) => (context: T, params: P) => number; other?: (arg: string) => void; }) => (params: P) => number +> : ^ ^^ ^^ ^^ ^^^^^ +>{ context: 1, callback: (params: N) => { return (a, b) => a + 1; }, other: (_) => {} // outer context-sensitive function} : { context: number; callback: (params: N) => (a: number, b: unknown) => number; other: (_: string) => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ + + context: 1, +>context : number +> : ^^^^^^ +>1 : 1 +> : ^ + + callback: (params: N) => { +>callback : (params: N) => (a: number, b: unknown) => number +> : ^ ^^ ^^ ^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ +>(params: N) => { return (a, b) => a + 1; } : (params: N) => (a: number, b: unknown) => number +> : ^ ^^ ^^ ^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ +>params : N +> : ^ + + return (a, b) => a + 1; +>(a, b) => a + 1 : (a: number, b: unknown) => number +> : ^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ +>a : number +> : ^^^^^^ +>b : unknown +> : ^^^^^^^ +>a + 1 : number +> : ^^^^^^ +>a : number +> : ^^^^^^ +>1 : 1 +> : ^ + + }, + other: (_) => {} // outer context-sensitive function +>other : (_: string) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>(_) => {} : (_: string) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>_ : string +> : ^^^^^^ + +}); + +// should error +export const result7 = fn4({ +>result7 : (params: unknown) => number +> : ^ ^^^^^^^^^^^^^^ +>fn4({ context: 1, callback: (params: N) => { return (a: boolean, b) => a ? 1 : 2; }, other: (_) => {} // outer context-sensitive function}) : (params: unknown) => number +> : ^ ^^^^^^^^^^^^^^ +>fn4 : (config: { context: T; callback: (params: P) => (context: T, params: P) => number; other?: (arg: string) => void; }) => (params: P) => number +> : ^ ^^ ^^ ^^ ^^^^^ +>{ context: 1, callback: (params: N) => { return (a: boolean, b) => a ? 1 : 2; }, other: (_) => {} // outer context-sensitive function} : { context: number; callback: (params: N) => (a: boolean, b: unknown) => 1 | 2; other: (_: string) => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ + + context: 1, +>context : number +> : ^^^^^^ +>1 : 1 +> : ^ + + callback: (params: N) => { +>callback : (params: N) => (a: boolean, b: unknown) => 1 | 2 +> : ^ ^^ ^^ ^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^ +>(params: N) => { return (a: boolean, b) => a ? 1 : 2; } : (params: N) => (a: boolean, b: unknown) => 1 | 2 +> : ^ ^^ ^^ ^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^ +>params : N +> : ^ + + return (a: boolean, b) => a ? 1 : 2; +>(a: boolean, b) => a ? 1 : 2 : (a: boolean, b: unknown) => 1 | 2 +> : ^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^ +>a : boolean +> : ^^^^^^^ +>b : unknown +> : ^^^^^^^ +>a ? 1 : 2 : 1 | 2 +> : ^^^^^ +>a : boolean +> : ^^^^^^^ +>1 : 1 +> : ^ +>2 : 2 +> : ^ + + }, + other: (_) => {} // outer context-sensitive function +>other : (_: string) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>(_) => {} : (_: string) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>_ : string +> : ^^^^^^ + +}); + + // should error +export const result8 = fn4({ +>result8 : (params: unknown) => number +> : ^ ^^^^^^^^^^^^^^ +>fn4({ context: 1, callback: (params: N) => { return (a, b) => true; }, other: (_) => {} // outer context-sensitive function}) : (params: unknown) => number +> : ^ ^^^^^^^^^^^^^^ +>fn4 : (config: { context: T; callback: (params: P) => (context: T, params: P) => number; other?: (arg: string) => void; }) => (params: P) => number +> : ^ ^^ ^^ ^^ ^^^^^ +>{ context: 1, callback: (params: N) => { return (a, b) => true; }, other: (_) => {} // outer context-sensitive function} : { context: number; callback: (params: N) => (a: number, b: unknown) => boolean; other: (_: string) => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ + + context: 1, +>context : number +> : ^^^^^^ +>1 : 1 +> : ^ + + callback: (params: N) => { +>callback : (params: N) => (a: number, b: unknown) => boolean +> : ^ ^^ ^^ ^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^ +>(params: N) => { return (a, b) => true; } : (params: N) => (a: number, b: unknown) => boolean +> : ^ ^^ ^^ ^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^ +>params : N +> : ^ + + return (a, b) => true; +>(a, b) => true : (a: number, b: unknown) => boolean +> : ^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^ +>a : number +> : ^^^^^^ +>b : unknown +> : ^^^^^^^ +>true : true +> : ^^^^ + + }, + other: (_) => {} // outer context-sensitive function +>other : (_: string) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>(_) => {} : (_: string) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>_ : string +> : ^^^^^^ + +}); + +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 result9 = fnGen1({ message: "foo" }, function* (n: number) { +>result9 : (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 result10 = fnGen1({ message: "foo" }, function* (n: N) { +>result10 : (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..0852c0cb0b1e8 --- /dev/null +++ b/tests/cases/compiler/contextualTypingGenericFunction2.ts @@ -0,0 +1,87 @@ +// @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 result1 = fn1({ message: "foo" }, function (n: number) { + this.message; +}); + +export const result2 = fn1({ message: "foo" }, function (n: N) { + this.message; +}); + +declare const fn2: , Ret>( + body: (first: string, ...args: Args) => Ret, +) => (...args: Args) => Ret; + +export const result3 = fn2(function (first, n: N) {}); + +declare const fn3: , Ret>( + body: (...args: Args) => (arg: string) => Ret, +) => (...args: Args) => Ret; + +export const result4 = fn3(function (n: N) { + return (arg) => { + return 10 + } +}); + +declare function fn4(config: { + context: T; + callback: (params: P) => (context: T, params: P) => number; + other?: (arg: string) => void; +}): (params: P) => number; + +export const result5 = fn4({ + context: 1, + callback: (params: N) => { + return (a, b) => a + 1; + }, +}); + +export const result6 = fn4({ + context: 1, + callback: (params: N) => { + return (a, b) => a + 1; + }, + other: (_) => {} // outer context-sensitive function +}); + +// should error +export const result7 = fn4({ + context: 1, + callback: (params: N) => { + return (a: boolean, b) => a ? 1 : 2; + }, + other: (_) => {} // outer context-sensitive function +}); + + // should error +export const result8 = fn4({ + context: 1, + callback: (params: N) => { + return (a, b) => true; + }, + other: (_) => {} // outer context-sensitive function +}); + +declare const fnGen1: , Ret>( + self: T, + body: (this: T, ...args: Args) => Generator, +) => (...args: Args) => Ret; + +export const result9 = fnGen1({ message: "foo" }, function* (n: number) { + this.message; +}); + +export const result10 = 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" });