diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 40385062b1b..f89e1f4939b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17115,7 +17115,7 @@ namespace ts { function isUntypedFunctionCall(funcType: Type, apparentFuncType: Type, numCallSignatures: number, numConstructSignatures: number) { // We exclude union types because we may have a union of function types that happen to have no common signatures. return isTypeAny(funcType) || isTypeAny(apparentFuncType) && funcType.flags & TypeFlags.TypeParameter || - !numCallSignatures && !numConstructSignatures && !(funcType.flags & (TypeFlags.Union | TypeFlags.Never)) && isTypeAssignableTo(funcType, globalFunctionType); + !numCallSignatures && !numConstructSignatures && !(apparentFuncType.flags & (TypeFlags.Union | TypeFlags.Never)) && isTypeAssignableTo(funcType, globalFunctionType); } function resolveNewExpression(node: NewExpression, candidatesOutArray: Signature[]): Signature { diff --git a/tests/baselines/reference/functionCallOnConstrainedTypeVariable.errors.txt b/tests/baselines/reference/functionCallOnConstrainedTypeVariable.errors.txt new file mode 100644 index 00000000000..1ff56c7612f --- /dev/null +++ b/tests/baselines/reference/functionCallOnConstrainedTypeVariable.errors.txt @@ -0,0 +1,35 @@ +tests/cases/compiler/functionCallOnConstrainedTypeVariable.ts(11,3): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type '((x: number) => string) | ((x: boolean) => string)' has no compatible call signatures. +tests/cases/compiler/functionCallOnConstrainedTypeVariable.ts(15,3): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type '((x: number) => string) | ((x: boolean) => string)' has no compatible call signatures. +tests/cases/compiler/functionCallOnConstrainedTypeVariable.ts(18,3): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type '((x: number) => string) | ((x: boolean) => string)' has no compatible call signatures. +tests/cases/compiler/functionCallOnConstrainedTypeVariable.ts(19,3): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type '((x: number) => string) | ((x: boolean) => string)' has no compatible call signatures. + + +==== tests/cases/compiler/functionCallOnConstrainedTypeVariable.ts (4 errors) ==== + // Repro from #20196 + + type A = { + a: (x: number) => string + }; + type B = { + a: (x: boolean) => string + }; + + function call0(p: A | B) { + p.a("s"); // Error + ~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type '((x: number) => string) | ((x: boolean) => string)' has no compatible call signatures. + } + + function callN(p: T) { + p.a("s"); // Error + ~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type '((x: number) => string) | ((x: boolean) => string)' has no compatible call signatures. + + var a: T["a"] = p.a; + a(""); // Error + ~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type '((x: number) => string) | ((x: boolean) => string)' has no compatible call signatures. + a("", "", "", ""); // Error + ~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type '((x: number) => string) | ((x: boolean) => string)' has no compatible call signatures. + } \ No newline at end of file diff --git a/tests/baselines/reference/functionCallOnConstrainedTypeVariable.js b/tests/baselines/reference/functionCallOnConstrainedTypeVariable.js new file mode 100644 index 00000000000..34eab55aafe --- /dev/null +++ b/tests/baselines/reference/functionCallOnConstrainedTypeVariable.js @@ -0,0 +1,34 @@ +//// [functionCallOnConstrainedTypeVariable.ts] +// Repro from #20196 + +type A = { + a: (x: number) => string +}; +type B = { + a: (x: boolean) => string +}; + +function call0(p: A | B) { + p.a("s"); // Error +} + +function callN(p: T) { + p.a("s"); // Error + + var a: T["a"] = p.a; + a(""); // Error + a("", "", "", ""); // Error +} + +//// [functionCallOnConstrainedTypeVariable.js] +"use strict"; +// Repro from #20196 +function call0(p) { + p.a("s"); // Error +} +function callN(p) { + p.a("s"); // Error + var a = p.a; + a(""); // Error + a("", "", "", ""); // Error +} diff --git a/tests/baselines/reference/functionCallOnConstrainedTypeVariable.symbols b/tests/baselines/reference/functionCallOnConstrainedTypeVariable.symbols new file mode 100644 index 00000000000..e5bdcff342b --- /dev/null +++ b/tests/baselines/reference/functionCallOnConstrainedTypeVariable.symbols @@ -0,0 +1,58 @@ +=== tests/cases/compiler/functionCallOnConstrainedTypeVariable.ts === +// Repro from #20196 + +type A = { +>A : Symbol(A, Decl(functionCallOnConstrainedTypeVariable.ts, 0, 0)) + + a: (x: number) => string +>a : Symbol(a, Decl(functionCallOnConstrainedTypeVariable.ts, 2, 10)) +>x : Symbol(x, Decl(functionCallOnConstrainedTypeVariable.ts, 3, 6)) + +}; +type B = { +>B : Symbol(B, Decl(functionCallOnConstrainedTypeVariable.ts, 4, 2)) + + a: (x: boolean) => string +>a : Symbol(a, Decl(functionCallOnConstrainedTypeVariable.ts, 5, 10)) +>x : Symbol(x, Decl(functionCallOnConstrainedTypeVariable.ts, 6, 6)) + +}; + +function call0(p: A | B) { +>call0 : Symbol(call0, Decl(functionCallOnConstrainedTypeVariable.ts, 7, 2)) +>p : Symbol(p, Decl(functionCallOnConstrainedTypeVariable.ts, 9, 15)) +>A : Symbol(A, Decl(functionCallOnConstrainedTypeVariable.ts, 0, 0)) +>B : Symbol(B, Decl(functionCallOnConstrainedTypeVariable.ts, 4, 2)) + + p.a("s"); // Error +>p.a : Symbol(a, Decl(functionCallOnConstrainedTypeVariable.ts, 2, 10), Decl(functionCallOnConstrainedTypeVariable.ts, 5, 10)) +>p : Symbol(p, Decl(functionCallOnConstrainedTypeVariable.ts, 9, 15)) +>a : Symbol(a, Decl(functionCallOnConstrainedTypeVariable.ts, 2, 10), Decl(functionCallOnConstrainedTypeVariable.ts, 5, 10)) +} + +function callN(p: T) { +>callN : Symbol(callN, Decl(functionCallOnConstrainedTypeVariable.ts, 11, 1)) +>T : Symbol(T, Decl(functionCallOnConstrainedTypeVariable.ts, 13, 15)) +>A : Symbol(A, Decl(functionCallOnConstrainedTypeVariable.ts, 0, 0)) +>B : Symbol(B, Decl(functionCallOnConstrainedTypeVariable.ts, 4, 2)) +>p : Symbol(p, Decl(functionCallOnConstrainedTypeVariable.ts, 13, 32)) +>T : Symbol(T, Decl(functionCallOnConstrainedTypeVariable.ts, 13, 15)) + + p.a("s"); // Error +>p.a : Symbol(a, Decl(functionCallOnConstrainedTypeVariable.ts, 2, 10), Decl(functionCallOnConstrainedTypeVariable.ts, 5, 10)) +>p : Symbol(p, Decl(functionCallOnConstrainedTypeVariable.ts, 13, 32)) +>a : Symbol(a, Decl(functionCallOnConstrainedTypeVariable.ts, 2, 10), Decl(functionCallOnConstrainedTypeVariable.ts, 5, 10)) + + var a: T["a"] = p.a; +>a : Symbol(a, Decl(functionCallOnConstrainedTypeVariable.ts, 16, 5)) +>T : Symbol(T, Decl(functionCallOnConstrainedTypeVariable.ts, 13, 15)) +>p.a : Symbol(a, Decl(functionCallOnConstrainedTypeVariable.ts, 2, 10), Decl(functionCallOnConstrainedTypeVariable.ts, 5, 10)) +>p : Symbol(p, Decl(functionCallOnConstrainedTypeVariable.ts, 13, 32)) +>a : Symbol(a, Decl(functionCallOnConstrainedTypeVariable.ts, 2, 10), Decl(functionCallOnConstrainedTypeVariable.ts, 5, 10)) + + a(""); // Error +>a : Symbol(a, Decl(functionCallOnConstrainedTypeVariable.ts, 16, 5)) + + a("", "", "", ""); // Error +>a : Symbol(a, Decl(functionCallOnConstrainedTypeVariable.ts, 16, 5)) +} diff --git a/tests/baselines/reference/functionCallOnConstrainedTypeVariable.types b/tests/baselines/reference/functionCallOnConstrainedTypeVariable.types new file mode 100644 index 00000000000..9c6d349fac9 --- /dev/null +++ b/tests/baselines/reference/functionCallOnConstrainedTypeVariable.types @@ -0,0 +1,69 @@ +=== tests/cases/compiler/functionCallOnConstrainedTypeVariable.ts === +// Repro from #20196 + +type A = { +>A : A + + a: (x: number) => string +>a : (x: number) => string +>x : number + +}; +type B = { +>B : B + + a: (x: boolean) => string +>a : (x: boolean) => string +>x : boolean + +}; + +function call0(p: A | B) { +>call0 : (p: A | B) => void +>p : A | B +>A : A +>B : B + + p.a("s"); // Error +>p.a("s") : any +>p.a : ((x: number) => string) | ((x: boolean) => string) +>p : A | B +>a : ((x: number) => string) | ((x: boolean) => string) +>"s" : "s" +} + +function callN(p: T) { +>callN : (p: T) => void +>T : T +>A : A +>B : B +>p : T +>T : T + + p.a("s"); // Error +>p.a("s") : any +>p.a : ((x: number) => string) | ((x: boolean) => string) +>p : T +>a : ((x: number) => string) | ((x: boolean) => string) +>"s" : "s" + + var a: T["a"] = p.a; +>a : T["a"] +>T : T +>p.a : ((x: number) => string) | ((x: boolean) => string) +>p : T +>a : ((x: number) => string) | ((x: boolean) => string) + + a(""); // Error +>a("") : any +>a : T["a"] +>"" : "" + + a("", "", "", ""); // Error +>a("", "", "", "") : any +>a : T["a"] +>"" : "" +>"" : "" +>"" : "" +>"" : "" +} diff --git a/tests/cases/compiler/functionCallOnConstrainedTypeVariable.ts b/tests/cases/compiler/functionCallOnConstrainedTypeVariable.ts new file mode 100644 index 00000000000..8ceb578dc0a --- /dev/null +++ b/tests/cases/compiler/functionCallOnConstrainedTypeVariable.ts @@ -0,0 +1,22 @@ +// @strict: true + +// Repro from #20196 + +type A = { + a: (x: number) => string +}; +type B = { + a: (x: boolean) => string +}; + +function call0(p: A | B) { + p.a("s"); // Error +} + +function callN(p: T) { + p.a("s"); // Error + + var a: T["a"] = p.a; + a(""); // Error + a("", "", "", ""); // Error +} \ No newline at end of file