Prefer non-partial signature match in non-generic case (#55447)

Co-authored-by: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com>
This commit is contained in:
Mateusz Burzyński 2023-11-30 15:49:40 +01:00 committed by GitHub
parent 7216ee0bb8
commit 0a87761521
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 65 additions and 14 deletions

View File

@ -13242,9 +13242,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
let result: Signature[] | undefined;
for (let i = 0; i < signatureLists.length; i++) {
// Allow matching non-generic signatures to have excess parameters and different return types.
// Allow matching non-generic signatures to have excess parameters (as a fallback if exact parameter match is not found) and different return types.
// Prefer matching this types if possible.
const match = i === listIndex ? signature : findMatchingSignature(signatureLists[i], signature, /*partialMatch*/ true, /*ignoreThisTypes*/ false, /*ignoreReturnTypes*/ true);
const match = i === listIndex
? signature
: findMatchingSignature(signatureLists[i], signature, /*partialMatch*/ false, /*ignoreThisTypes*/ false, /*ignoreReturnTypes*/ true)
|| findMatchingSignature(signatureLists[i], signature, /*partialMatch*/ true, /*ignoreThisTypes*/ false, /*ignoreReturnTypes*/ true);
if (!match) {
return undefined;
}

View File

@ -6,12 +6,7 @@ unionTypeCallSignatures6.ts(38,4): error TS2349: This expression is not callable
unionTypeCallSignatures6.ts(39,1): error TS2684: The 'this' context of type 'A & C & { f0: F0 | F3; f1: F1 | F3; f2: F1 | F4; f3: F3 | F4; f4: F3 | F5; }' is not assignable to method's 'this' of type 'B'.
Property 'b' is missing in type 'A & C & { f0: F0 | F3; f1: F1 | F3; f2: F1 | F4; f3: F3 | F4; f4: F3 | F5; }' but required in type 'B'.
unionTypeCallSignatures6.ts(48,1): error TS2684: The 'this' context of type 'void' is not assignable to method's 'this' of type 'A & B'.
unionTypeCallSignatures6.ts(55,1): error TS2769: No overload matches this call.
Overload 1 of 2, '(this: A & B & C): void', gave the following error.
The 'this' context of type 'void' is not assignable to method's 'this' of type 'A & B & C'.
Type 'void' is not assignable to type 'A'.
Overload 2 of 2, '(this: A & B): void', gave the following error.
The 'this' context of type 'void' is not assignable to method's 'this' of type 'A & B'.
unionTypeCallSignatures6.ts(55,1): error TS2684: The 'this' context of type 'void' is not assignable to method's 'this' of type 'A & B'.
==== unionTypeCallSignatures6.ts (6 errors) ====
@ -85,10 +80,5 @@ unionTypeCallSignatures6.ts(55,1): error TS2769: No overload matches this call.
declare var f4: F6 | F7;
f4(); // error
~~~~
!!! error TS2769: No overload matches this call.
!!! error TS2769: Overload 1 of 2, '(this: A & B & C): void', gave the following error.
!!! error TS2769: The 'this' context of type 'void' is not assignable to method's 'this' of type 'A & B & C'.
!!! error TS2769: Type 'void' is not assignable to type 'A'.
!!! error TS2769: Overload 2 of 2, '(this: A & B): void', gave the following error.
!!! error TS2769: The 'this' context of type 'void' is not assignable to method's 'this' of type 'A & B'.
!!! error TS2684: The 'this' context of type 'void' is not assignable to method's 'this' of type 'A & B'.

View File

@ -0,0 +1,26 @@
//// [tests/cases/conformance/types/union/unionTypeCallSignatures7.ts] ////
=== unionTypeCallSignatures7.ts ===
// https://github.com/microsoft/TypeScript/issues/55203
interface Callable<Name extends string> {
>Callable : Symbol(Callable, Decl(unionTypeCallSignatures7.ts, 0, 0))
>Name : Symbol(Name, Decl(unionTypeCallSignatures7.ts, 2, 19))
(): `${Name} without id`;
>Name : Symbol(Name, Decl(unionTypeCallSignatures7.ts, 2, 19))
(id: number): `${Name} with id`;
>id : Symbol(id, Decl(unionTypeCallSignatures7.ts, 4, 3))
>Name : Symbol(Name, Decl(unionTypeCallSignatures7.ts, 2, 19))
}
declare const f: Callable<"A"> | Callable<"B">;
>f : Symbol(f, Decl(unionTypeCallSignatures7.ts, 7, 13))
>Callable : Symbol(Callable, Decl(unionTypeCallSignatures7.ts, 0, 0))
>Callable : Symbol(Callable, Decl(unionTypeCallSignatures7.ts, 0, 0))
const result = f(123);
>result : Symbol(result, Decl(unionTypeCallSignatures7.ts, 8, 5))
>f : Symbol(f, Decl(unionTypeCallSignatures7.ts, 7, 13))

View File

@ -0,0 +1,20 @@
//// [tests/cases/conformance/types/union/unionTypeCallSignatures7.ts] ////
=== unionTypeCallSignatures7.ts ===
// https://github.com/microsoft/TypeScript/issues/55203
interface Callable<Name extends string> {
(): `${Name} without id`;
(id: number): `${Name} with id`;
>id : number
}
declare const f: Callable<"A"> | Callable<"B">;
>f : Callable<"A"> | Callable<"B">
const result = f(123);
>result : "A with id" | "B with id"
>f(123) : "A with id" | "B with id"
>f : Callable<"A"> | Callable<"B">
>123 : 123

View File

@ -0,0 +1,12 @@
// @strict: true
// @noEmit: true
// https://github.com/microsoft/TypeScript/issues/55203
interface Callable<Name extends string> {
(): `${Name} without id`;
(id: number): `${Name} with id`;
}
declare const f: Callable<"A"> | Callable<"B">;
const result = f(123);