diff --git a/tsc/internal/checker/checker.go b/tsc/internal/checker/checker.go index fb3c33c01b814..50dfdf1f352b0 100644 --- a/tsc/internal/checker/checker.go +++ b/tsc/internal/checker/checker.go @@ -10285,7 +10285,9 @@ func (c *Checker) contextuallyCheckFunctionExpressionOrObjectLiteralMethod(node } } if contextualSignature != nil && c.getReturnTypeFromAnnotation(node) == nil && signature.resolvedReturnType == nil { - returnType := c.getReturnTypeFromBody(node, checkMode) + // resolvedReturnType is cached indefinitely, so the return type here has to be computed without CheckModeSkipContextSensitive; + // otherwise anyFunctionType could leak as part of the computed (and cached) return type. + returnType := c.getReturnTypeFromBody(node, checkMode&^CheckModeSkipContextSensitive) if signature.resolvedReturnType == nil { signature.resolvedReturnType = returnType } diff --git a/tsc/testdata/baselines/reference/compiler/contextualTypingGenericFunction2.errors.txt b/tsc/testdata/baselines/reference/compiler/contextualTypingGenericFunction2.errors.txt new file mode 100644 index 0000000000000..d9617585b65f4 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/contextualTypingGenericFunction2.errors.txt @@ -0,0 +1,115 @@ +contextualTypingGenericFunction2.ts(10,3): error TS2322: Type '(params: T) => (a: boolean, b: unknown) => 0 | 1' is not assignable to type '(params: T) => (context: number, params: T) => number'. + Type '(a: boolean, b: unknown) => 0 | 1' is not assignable to type '(context: number, params: T) => number'. + Types of parameters 'a' and 'context' are incompatible. + Type 'number' is not assignable to type 'boolean'. +contextualTypingGenericFunction2.ts(18,3): error TS2322: Type '(params: T) => (a: number, b: unknown) => boolean' is not assignable to type '(params: T) => (context: number, params: T) => number'. + Type '(a: number, b: unknown) => boolean' is not assignable to type '(context: number, params: T) => number'. + Type 'boolean' is not assignable to type 'number'. +contextualTypingGenericFunction2.ts(26,3): error TS2322: Type '(params: T) => (a: number, b: unknown) => boolean' is not assignable to type '(params: T) => (context: number, params: T) => number'. + Type '(a: number, b: unknown) => boolean' is not assignable to type '(context: number, params: T) => number'. + Type 'boolean' is not assignable to type 'number'. +contextualTypingGenericFunction2.ts(39,3): error TS2322: Type '(params: T) => (a: boolean, b: unknown) => 0 | 1' is not assignable to type '(params: unknown) => (context: number, params: unknown) => number'. + Type '(a: boolean, b: unknown) => 0 | 1' is not assignable to type '(context: number, params: unknown) => number'. + Types of parameters 'a' and 'context' are incompatible. + Type 'number' is not assignable to type 'boolean'. +contextualTypingGenericFunction2.ts(47,3): error TS2322: Type '(params: T) => (a: number, b: unknown) => boolean' is not assignable to type '(params: unknown) => (context: number, params: unknown) => number'. + Type '(a: number, b: unknown) => boolean' is not assignable to type '(context: number, params: unknown) => number'. + Type 'boolean' is not assignable to type 'number'. +contextualTypingGenericFunction2.ts(55,3): error TS2322: Type '(params: T) => (a: number, b: unknown) => boolean' is not assignable to type '(params: unknown) => (context: number, params: unknown) => number'. + Type '(a: number, b: unknown) => boolean' is not assignable to type '(context: number, params: unknown) => number'. + Type 'boolean' is not assignable to type 'number'. + + +==== contextualTypingGenericFunction2.ts (6 errors) ==== + // https://github.com/microsoft/TypeScript/issues/61979 + + declare function fn

(config: { + callback: (params: P) => (context: number, params: P) => number; + unrelated?: (arg: string) => void; + }): (params: P) => number; + + // should error + export const result1 = fn({ + callback: (params: T) => { + ~~~~~~~~ +!!! error TS2322: Type '(params: T) => (a: boolean, b: unknown) => 0 | 1' is not assignable to type '(params: T) => (context: number, params: T) => number'. +!!! error TS2322: Type '(a: boolean, b: unknown) => 0 | 1' is not assignable to type '(context: number, params: T) => number'. +!!! error TS2322: Types of parameters 'a' and 'context' are incompatible. +!!! error TS2322: Type 'number' is not assignable to type 'boolean'. +!!! related TS6500 contextualTypingGenericFunction2.ts:4:3: The expected type comes from property 'callback' which is declared here on type '{ callback: (params: T) => (context: number, params: T) => number; unrelated?: ((arg: string) => void) | undefined; }' + return (a: boolean, b) => (a ? 1 : 0); + }, + unrelated: (_) => {}, + }); + + // should error + export const result2 = fn({ + callback: (params: T) => { + ~~~~~~~~ +!!! error TS2322: Type '(params: T) => (a: number, b: unknown) => boolean' is not assignable to type '(params: T) => (context: number, params: T) => number'. +!!! error TS2322: Type '(a: number, b: unknown) => boolean' is not assignable to type '(context: number, params: T) => number'. +!!! error TS2322: Type 'boolean' is not assignable to type 'number'. +!!! related TS6500 contextualTypingGenericFunction2.ts:4:3: The expected type comes from property 'callback' which is declared here on type '{ callback: (params: T) => (context: number, params: T) => number; unrelated?: ((arg: string) => void) | undefined; }' + return (a, b): boolean => true; + }, + unrelated: (_) => {}, + }); + + // should error + export const result3 = fn({ + callback: (params: T) => { + ~~~~~~~~ +!!! error TS2322: Type '(params: T) => (a: number, b: unknown) => boolean' is not assignable to type '(params: T) => (context: number, params: T) => number'. +!!! error TS2322: Type '(a: number, b: unknown) => boolean' is not assignable to type '(context: number, params: T) => number'. +!!! error TS2322: Type 'boolean' is not assignable to type 'number'. +!!! related TS6500 contextualTypingGenericFunction2.ts:4:3: The expected type comes from property 'callback' which is declared here on type '{ callback: (params: T) => (context: number, params: T) => number; unrelated?: ((arg: string) => void) | undefined; }' + return (a, b) => true; + }, + unrelated: (_) => {}, + }); + + declare function fn2

(config: { + callback: (params: P) => (context: number, params: P) => number; + unrelated?: (arg: string) => void; + }): any; + + // should error + export const result4 = fn2({ + callback: (params: T) => { + ~~~~~~~~ +!!! error TS2322: Type '(params: T) => (a: boolean, b: unknown) => 0 | 1' is not assignable to type '(params: unknown) => (context: number, params: unknown) => number'. +!!! error TS2322: Type '(a: boolean, b: unknown) => 0 | 1' is not assignable to type '(context: number, params: unknown) => number'. +!!! error TS2322: Types of parameters 'a' and 'context' are incompatible. +!!! error TS2322: Type 'number' is not assignable to type 'boolean'. +!!! related TS6500 contextualTypingGenericFunction2.ts:33:3: The expected type comes from property 'callback' which is declared here on type '{ callback: (params: unknown) => (context: number, params: unknown) => number; unrelated?: ((arg: string) => void) | undefined; }' + return (a: boolean, b) => (a ? 1 : 0); + }, + unrelated: (_) => {}, + }); + + // should error + export const result5 = fn2({ + callback: (params: T) => { + ~~~~~~~~ +!!! error TS2322: Type '(params: T) => (a: number, b: unknown) => boolean' is not assignable to type '(params: unknown) => (context: number, params: unknown) => number'. +!!! error TS2322: Type '(a: number, b: unknown) => boolean' is not assignable to type '(context: number, params: unknown) => number'. +!!! error TS2322: Type 'boolean' is not assignable to type 'number'. +!!! related TS6500 contextualTypingGenericFunction2.ts:33:3: The expected type comes from property 'callback' which is declared here on type '{ callback: (params: unknown) => (context: number, params: unknown) => number; unrelated?: ((arg: string) => void) | undefined; }' + return (a, b): boolean => true; + }, + unrelated: (_) => {}, + }); + + // should error + export const result6 = fn2({ + callback: (params: T) => { + ~~~~~~~~ +!!! error TS2322: Type '(params: T) => (a: number, b: unknown) => boolean' is not assignable to type '(params: unknown) => (context: number, params: unknown) => number'. +!!! error TS2322: Type '(a: number, b: unknown) => boolean' is not assignable to type '(context: number, params: unknown) => number'. +!!! error TS2322: Type 'boolean' is not assignable to type 'number'. +!!! related TS6500 contextualTypingGenericFunction2.ts:33:3: The expected type comes from property 'callback' which is declared here on type '{ callback: (params: unknown) => (context: number, params: unknown) => number; unrelated?: ((arg: string) => void) | undefined; }' + return (a, b) => true; + }, + unrelated: (_) => {}, + }); + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/contextualTypingGenericFunction2.symbols b/tsc/testdata/baselines/reference/compiler/contextualTypingGenericFunction2.symbols new file mode 100644 index 0000000000000..e319edad2ba7f --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/contextualTypingGenericFunction2.symbols @@ -0,0 +1,179 @@ +//// [tests/cases/compiler/contextualTypingGenericFunction2.ts] //// + +=== contextualTypingGenericFunction2.ts === +// https://github.com/microsoft/TypeScript/issues/61979 + +declare function fn

(config: { +>fn : Symbol(fn, Decl(contextualTypingGenericFunction2.ts, 0, 0)) +>P : Symbol(P, Decl(contextualTypingGenericFunction2.ts, 2, 20)) +>config : Symbol(config, Decl(contextualTypingGenericFunction2.ts, 2, 23)) + + callback: (params: P) => (context: number, params: P) => number; +>callback : Symbol(callback, Decl(contextualTypingGenericFunction2.ts, 2, 32)) +>params : Symbol(params, Decl(contextualTypingGenericFunction2.ts, 3, 13)) +>P : Symbol(P, Decl(contextualTypingGenericFunction2.ts, 2, 20)) +>context : Symbol(context, Decl(contextualTypingGenericFunction2.ts, 3, 28)) +>params : Symbol(params, Decl(contextualTypingGenericFunction2.ts, 3, 44)) +>P : Symbol(P, Decl(contextualTypingGenericFunction2.ts, 2, 20)) + + unrelated?: (arg: string) => void; +>unrelated : Symbol(unrelated, Decl(contextualTypingGenericFunction2.ts, 3, 66)) +>arg : Symbol(arg, Decl(contextualTypingGenericFunction2.ts, 4, 15)) + +}): (params: P) => number; +>params : Symbol(params, Decl(contextualTypingGenericFunction2.ts, 5, 5)) +>P : Symbol(P, Decl(contextualTypingGenericFunction2.ts, 2, 20)) + +// should error +export const result1 = fn({ +>result1 : Symbol(result1, Decl(contextualTypingGenericFunction2.ts, 8, 12)) +>fn : Symbol(fn, Decl(contextualTypingGenericFunction2.ts, 0, 0)) + + callback: (params: T) => { +>callback : Symbol(callback, Decl(contextualTypingGenericFunction2.ts, 8, 27)) +>T : Symbol(T, Decl(contextualTypingGenericFunction2.ts, 9, 13)) +>params : Symbol(params, Decl(contextualTypingGenericFunction2.ts, 9, 17)) +>T : Symbol(T, Decl(contextualTypingGenericFunction2.ts, 9, 13)) + + return (a: boolean, b) => (a ? 1 : 0); +>a : Symbol(a, Decl(contextualTypingGenericFunction2.ts, 10, 12)) +>b : Symbol(b, Decl(contextualTypingGenericFunction2.ts, 10, 23)) +>a : Symbol(a, Decl(contextualTypingGenericFunction2.ts, 10, 12)) + + }, + unrelated: (_) => {}, +>unrelated : Symbol(unrelated, Decl(contextualTypingGenericFunction2.ts, 11, 4)) +>_ : Symbol(_, Decl(contextualTypingGenericFunction2.ts, 12, 14)) + +}); + +// should error +export const result2 = fn({ +>result2 : Symbol(result2, Decl(contextualTypingGenericFunction2.ts, 16, 12)) +>fn : Symbol(fn, Decl(contextualTypingGenericFunction2.ts, 0, 0)) + + callback: (params: T) => { +>callback : Symbol(callback, Decl(contextualTypingGenericFunction2.ts, 16, 27)) +>T : Symbol(T, Decl(contextualTypingGenericFunction2.ts, 17, 13)) +>params : Symbol(params, Decl(contextualTypingGenericFunction2.ts, 17, 17)) +>T : Symbol(T, Decl(contextualTypingGenericFunction2.ts, 17, 13)) + + return (a, b): boolean => true; +>a : Symbol(a, Decl(contextualTypingGenericFunction2.ts, 18, 12)) +>b : Symbol(b, Decl(contextualTypingGenericFunction2.ts, 18, 14)) + + }, + unrelated: (_) => {}, +>unrelated : Symbol(unrelated, Decl(contextualTypingGenericFunction2.ts, 19, 4)) +>_ : Symbol(_, Decl(contextualTypingGenericFunction2.ts, 20, 14)) + +}); + +// should error +export const result3 = fn({ +>result3 : Symbol(result3, Decl(contextualTypingGenericFunction2.ts, 24, 12)) +>fn : Symbol(fn, Decl(contextualTypingGenericFunction2.ts, 0, 0)) + + callback: (params: T) => { +>callback : Symbol(callback, Decl(contextualTypingGenericFunction2.ts, 24, 27)) +>T : Symbol(T, Decl(contextualTypingGenericFunction2.ts, 25, 13)) +>params : Symbol(params, Decl(contextualTypingGenericFunction2.ts, 25, 17)) +>T : Symbol(T, Decl(contextualTypingGenericFunction2.ts, 25, 13)) + + return (a, b) => true; +>a : Symbol(a, Decl(contextualTypingGenericFunction2.ts, 26, 12)) +>b : Symbol(b, Decl(contextualTypingGenericFunction2.ts, 26, 14)) + + }, + unrelated: (_) => {}, +>unrelated : Symbol(unrelated, Decl(contextualTypingGenericFunction2.ts, 27, 4)) +>_ : Symbol(_, Decl(contextualTypingGenericFunction2.ts, 28, 14)) + +}); + +declare function fn2

(config: { +>fn2 : Symbol(fn2, Decl(contextualTypingGenericFunction2.ts, 29, 3)) +>P : Symbol(P, Decl(contextualTypingGenericFunction2.ts, 31, 21)) +>config : Symbol(config, Decl(contextualTypingGenericFunction2.ts, 31, 24)) + + callback: (params: P) => (context: number, params: P) => number; +>callback : Symbol(callback, Decl(contextualTypingGenericFunction2.ts, 31, 33)) +>params : Symbol(params, Decl(contextualTypingGenericFunction2.ts, 32, 13)) +>P : Symbol(P, Decl(contextualTypingGenericFunction2.ts, 31, 21)) +>context : Symbol(context, Decl(contextualTypingGenericFunction2.ts, 32, 28)) +>params : Symbol(params, Decl(contextualTypingGenericFunction2.ts, 32, 44)) +>P : Symbol(P, Decl(contextualTypingGenericFunction2.ts, 31, 21)) + + unrelated?: (arg: string) => void; +>unrelated : Symbol(unrelated, Decl(contextualTypingGenericFunction2.ts, 32, 66)) +>arg : Symbol(arg, Decl(contextualTypingGenericFunction2.ts, 33, 15)) + +}): any; + +// should error +export const result4 = fn2({ +>result4 : Symbol(result4, Decl(contextualTypingGenericFunction2.ts, 37, 12)) +>fn2 : Symbol(fn2, Decl(contextualTypingGenericFunction2.ts, 29, 3)) + + callback: (params: T) => { +>callback : Symbol(callback, Decl(contextualTypingGenericFunction2.ts, 37, 28)) +>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: boolean, b) => (a ? 1 : 0); +>a : Symbol(a, Decl(contextualTypingGenericFunction2.ts, 39, 12)) +>b : Symbol(b, Decl(contextualTypingGenericFunction2.ts, 39, 23)) +>a : Symbol(a, Decl(contextualTypingGenericFunction2.ts, 39, 12)) + + }, + unrelated: (_) => {}, +>unrelated : Symbol(unrelated, Decl(contextualTypingGenericFunction2.ts, 40, 4)) +>_ : Symbol(_, Decl(contextualTypingGenericFunction2.ts, 41, 14)) + +}); + +// should error +export const result5 = fn2({ +>result5 : Symbol(result5, Decl(contextualTypingGenericFunction2.ts, 45, 12)) +>fn2 : Symbol(fn2, Decl(contextualTypingGenericFunction2.ts, 29, 3)) + + callback: (params: T) => { +>callback : Symbol(callback, Decl(contextualTypingGenericFunction2.ts, 45, 28)) +>T : Symbol(T, Decl(contextualTypingGenericFunction2.ts, 46, 13)) +>params : Symbol(params, Decl(contextualTypingGenericFunction2.ts, 46, 17)) +>T : Symbol(T, Decl(contextualTypingGenericFunction2.ts, 46, 13)) + + return (a, b): boolean => true; +>a : Symbol(a, Decl(contextualTypingGenericFunction2.ts, 47, 12)) +>b : Symbol(b, Decl(contextualTypingGenericFunction2.ts, 47, 14)) + + }, + unrelated: (_) => {}, +>unrelated : Symbol(unrelated, Decl(contextualTypingGenericFunction2.ts, 48, 4)) +>_ : Symbol(_, Decl(contextualTypingGenericFunction2.ts, 49, 14)) + +}); + +// should error +export const result6 = fn2({ +>result6 : Symbol(result6, Decl(contextualTypingGenericFunction2.ts, 53, 12)) +>fn2 : Symbol(fn2, Decl(contextualTypingGenericFunction2.ts, 29, 3)) + + callback: (params: T) => { +>callback : Symbol(callback, Decl(contextualTypingGenericFunction2.ts, 53, 28)) +>T : Symbol(T, Decl(contextualTypingGenericFunction2.ts, 54, 13)) +>params : Symbol(params, Decl(contextualTypingGenericFunction2.ts, 54, 17)) +>T : Symbol(T, Decl(contextualTypingGenericFunction2.ts, 54, 13)) + + return (a, b) => true; +>a : Symbol(a, Decl(contextualTypingGenericFunction2.ts, 55, 12)) +>b : Symbol(b, Decl(contextualTypingGenericFunction2.ts, 55, 14)) + + }, + unrelated: (_) => {}, +>unrelated : Symbol(unrelated, Decl(contextualTypingGenericFunction2.ts, 56, 4)) +>_ : Symbol(_, Decl(contextualTypingGenericFunction2.ts, 57, 14)) + +}); + diff --git a/tsc/testdata/baselines/reference/compiler/contextualTypingGenericFunction2.types b/tsc/testdata/baselines/reference/compiler/contextualTypingGenericFunction2.types new file mode 100644 index 0000000000000..1660f8bf544ad --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/contextualTypingGenericFunction2.types @@ -0,0 +1,202 @@ +//// [tests/cases/compiler/contextualTypingGenericFunction2.ts] //// + +=== contextualTypingGenericFunction2.ts === +// https://github.com/microsoft/TypeScript/issues/61979 + +declare function fn

(config: { +>fn :

(config: { callback: (params: P) => (context: number, params: P) => number; unrelated?: (arg: string) => void; }) => (params: P) => number +>config : { callback: (params: P) => (context: number, params: P) => number; unrelated?: (arg: string) => void; } + + callback: (params: P) => (context: number, params: P) => number; +>callback : (params: P) => (context: number, params: P) => number +>params : P +>context : number +>params : P + + unrelated?: (arg: string) => void; +>unrelated : ((arg: string) => void) | undefined +>arg : string + +}): (params: P) => number; +>params : P + +// should error +export const result1 = fn({ +>result1 : (params: unknown) => number +>fn({ callback: (params: T) => { return (a: boolean, b) => (a ? 1 : 0); }, unrelated: (_) => {},}) : (params: unknown) => number +>fn :

(config: { callback: (params: P) => (context: number, params: P) => number; unrelated?: (arg: string) => void; }) => (params: P) => number +>{ callback: (params: T) => { return (a: boolean, b) => (a ? 1 : 0); }, unrelated: (_) => {},} : { callback: (params: T) => (a: boolean, b: unknown) => 0 | 1; unrelated: (_: string) => void; } + + callback: (params: T) => { +>callback : (params: T) => (a: boolean, b: unknown) => 0 | 1 +>(params: T) => { return (a: boolean, b) => (a ? 1 : 0); } : (params: T) => (a: boolean, b: unknown) => 0 | 1 +>params : T + + return (a: boolean, b) => (a ? 1 : 0); +>(a: boolean, b) => (a ? 1 : 0) : (a: boolean, b: unknown) => 0 | 1 +>a : boolean +>b : unknown +>(a ? 1 : 0) : 0 | 1 +>a ? 1 : 0 : 0 | 1 +>a : boolean +>1 : 1 +>0 : 0 + + }, + unrelated: (_) => {}, +>unrelated : (_: string) => void +>(_) => {} : (_: string) => void +>_ : string + +}); + +// should error +export const result2 = fn({ +>result2 : (params: unknown) => number +>fn({ callback: (params: T) => { return (a, b): boolean => true; }, unrelated: (_) => {},}) : (params: unknown) => number +>fn :

(config: { callback: (params: P) => (context: number, params: P) => number; unrelated?: (arg: string) => void; }) => (params: P) => number +>{ callback: (params: T) => { return (a, b): boolean => true; }, unrelated: (_) => {},} : { callback: (params: T) => (a: number, b: unknown) => boolean; unrelated: (_: string) => void; } + + callback: (params: T) => { +>callback : (params: T) => (a: number, b: unknown) => boolean +>(params: T) => { return (a, b): boolean => true; } : (params: T) => (a: number, b: unknown) => boolean +>params : T + + return (a, b): boolean => true; +>(a, b): boolean => true : (a: number, b: unknown) => boolean +>a : number +>b : unknown +>true : true + + }, + unrelated: (_) => {}, +>unrelated : (_: string) => void +>(_) => {} : (_: string) => void +>_ : string + +}); + +// should error +export const result3 = fn({ +>result3 : (params: unknown) => number +>fn({ callback: (params: T) => { return (a, b) => true; }, unrelated: (_) => {},}) : (params: unknown) => number +>fn :

(config: { callback: (params: P) => (context: number, params: P) => number; unrelated?: (arg: string) => void; }) => (params: P) => number +>{ callback: (params: T) => { return (a, b) => true; }, unrelated: (_) => {},} : { callback: (params: T) => (a: number, b: unknown) => boolean; unrelated: (_: string) => void; } + + callback: (params: T) => { +>callback : (params: T) => (a: number, b: unknown) => boolean +>(params: T) => { return (a, b) => true; } : (params: T) => (a: number, b: unknown) => boolean +>params : T + + return (a, b) => true; +>(a, b) => true : (a: number, b: unknown) => boolean +>a : number +>b : unknown +>true : true + + }, + unrelated: (_) => {}, +>unrelated : (_: string) => void +>(_) => {} : (_: string) => void +>_ : string + +}); + +declare function fn2

(config: { +>fn2 :

(config: { callback: (params: P) => (context: number, params: P) => number; unrelated?: (arg: string) => void; }) => any +>config : { callback: (params: P) => (context: number, params: P) => number; unrelated?: (arg: string) => void; } + + callback: (params: P) => (context: number, params: P) => number; +>callback : (params: P) => (context: number, params: P) => number +>params : P +>context : number +>params : P + + unrelated?: (arg: string) => void; +>unrelated : ((arg: string) => void) | undefined +>arg : string + +}): any; + +// should error +export const result4 = fn2({ +>result4 : any +>fn2({ callback: (params: T) => { return (a: boolean, b) => (a ? 1 : 0); }, unrelated: (_) => {},}) : any +>fn2 :

(config: { callback: (params: P) => (context: number, params: P) => number; unrelated?: (arg: string) => void; }) => any +>{ callback: (params: T) => { return (a: boolean, b) => (a ? 1 : 0); }, unrelated: (_) => {},} : { callback: (params: T) => (a: boolean, b: unknown) => 0 | 1; unrelated: (_: string) => void; } + + callback: (params: T) => { +>callback : (params: T) => (a: boolean, b: unknown) => 0 | 1 +>(params: T) => { return (a: boolean, b) => (a ? 1 : 0); } : (params: T) => (a: boolean, b: unknown) => 0 | 1 +>params : T + + return (a: boolean, b) => (a ? 1 : 0); +>(a: boolean, b) => (a ? 1 : 0) : (a: boolean, b: unknown) => 0 | 1 +>a : boolean +>b : unknown +>(a ? 1 : 0) : 0 | 1 +>a ? 1 : 0 : 0 | 1 +>a : boolean +>1 : 1 +>0 : 0 + + }, + unrelated: (_) => {}, +>unrelated : (_: string) => void +>(_) => {} : (_: string) => void +>_ : string + +}); + +// should error +export const result5 = fn2({ +>result5 : any +>fn2({ callback: (params: T) => { return (a, b): boolean => true; }, unrelated: (_) => {},}) : any +>fn2 :

(config: { callback: (params: P) => (context: number, params: P) => number; unrelated?: (arg: string) => void; }) => any +>{ callback: (params: T) => { return (a, b): boolean => true; }, unrelated: (_) => {},} : { callback: (params: T) => (a: number, b: unknown) => boolean; unrelated: (_: string) => void; } + + callback: (params: T) => { +>callback : (params: T) => (a: number, b: unknown) => boolean +>(params: T) => { return (a, b): boolean => true; } : (params: T) => (a: number, b: unknown) => boolean +>params : T + + return (a, b): boolean => true; +>(a, b): boolean => true : (a: number, b: unknown) => boolean +>a : number +>b : unknown +>true : true + + }, + unrelated: (_) => {}, +>unrelated : (_: string) => void +>(_) => {} : (_: string) => void +>_ : string + +}); + +// should error +export const result6 = fn2({ +>result6 : any +>fn2({ callback: (params: T) => { return (a, b) => true; }, unrelated: (_) => {},}) : any +>fn2 :

(config: { callback: (params: P) => (context: number, params: P) => number; unrelated?: (arg: string) => void; }) => any +>{ callback: (params: T) => { return (a, b) => true; }, unrelated: (_) => {},} : { callback: (params: T) => (a: number, b: unknown) => boolean; unrelated: (_: string) => void; } + + callback: (params: T) => { +>callback : (params: T) => (a: number, b: unknown) => boolean +>(params: T) => { return (a, b) => true; } : (params: T) => (a: number, b: unknown) => boolean +>params : T + + return (a, b) => true; +>(a, b) => true : (a: number, b: unknown) => boolean +>a : number +>b : unknown +>true : true + + }, + unrelated: (_) => {}, +>unrelated : (_: string) => void +>(_) => {} : (_: string) => void +>_ : string + +}); + diff --git a/tsc/testdata/tests/cases/compiler/contextualTypingGenericFunction2.ts b/tsc/testdata/tests/cases/compiler/contextualTypingGenericFunction2.ts new file mode 100644 index 0000000000000..c57e81d414747 --- /dev/null +++ b/tsc/testdata/tests/cases/compiler/contextualTypingGenericFunction2.ts @@ -0,0 +1,62 @@ +// @strict: true +// @noEmit: true + +// https://github.com/microsoft/TypeScript/issues/61979 + +declare function fn

(config: { + callback: (params: P) => (context: number, params: P) => number; + unrelated?: (arg: string) => void; +}): (params: P) => number; + +// should error +export const result1 = fn({ + callback: (params: T) => { + return (a: boolean, b) => (a ? 1 : 0); + }, + unrelated: (_) => {}, +}); + +// should error +export const result2 = fn({ + callback: (params: T) => { + return (a, b): boolean => true; + }, + unrelated: (_) => {}, +}); + +// should error +export const result3 = fn({ + callback: (params: T) => { + return (a, b) => true; + }, + unrelated: (_) => {}, +}); + +declare function fn2

(config: { + callback: (params: P) => (context: number, params: P) => number; + unrelated?: (arg: string) => void; +}): any; + +// should error +export const result4 = fn2({ + callback: (params: T) => { + return (a: boolean, b) => (a ? 1 : 0); + }, + unrelated: (_) => {}, +}); + +// should error +export const result5 = fn2({ + callback: (params: T) => { + return (a, b): boolean => true; + }, + unrelated: (_) => {}, +}); + +// should error +export const result6 = fn2({ + callback: (params: T) => { + return (a, b) => true; + }, + unrelated: (_) => {}, +});