Merge pull request #5459 from Microsoft/partialSignatureMatching
Fix union type partial signature matching
This commit is contained in:
commit
9b4956fa11
4 changed files with 132 additions and 8 deletions
|
@ -5606,18 +5606,31 @@ namespace ts {
|
||||||
return compareTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp));
|
return compareTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isMatchingSignature(source: Signature, target: Signature, partialMatch: boolean) {
|
||||||
|
// A source signature matches a target signature if the two signatures have the same number of required,
|
||||||
|
// optional, and rest parameters.
|
||||||
|
if (source.parameters.length === target.parameters.length &&
|
||||||
|
source.minArgumentCount === target.minArgumentCount &&
|
||||||
|
source.hasRestParameter === target.hasRestParameter) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// A source signature partially matches a target signature if the target signature has no fewer required
|
||||||
|
// parameters and no more overall parameters than the source signature (where a signature with a rest
|
||||||
|
// parameter is always considered to have more overall parameters than one without).
|
||||||
|
if (partialMatch && source.minArgumentCount <= target.minArgumentCount && (
|
||||||
|
source.hasRestParameter && !target.hasRestParameter ||
|
||||||
|
source.hasRestParameter === target.hasRestParameter && source.parameters.length >= target.parameters.length)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
function compareSignatures(source: Signature, target: Signature, partialMatch: boolean, ignoreReturnTypes: boolean, compareTypes: (s: Type, t: Type) => Ternary): Ternary {
|
function compareSignatures(source: Signature, target: Signature, partialMatch: boolean, ignoreReturnTypes: boolean, compareTypes: (s: Type, t: Type) => Ternary): Ternary {
|
||||||
if (source === target) {
|
if (source === target) {
|
||||||
return Ternary.True;
|
return Ternary.True;
|
||||||
}
|
}
|
||||||
if (source.parameters.length !== target.parameters.length ||
|
if (!(isMatchingSignature(source, target, partialMatch))) {
|
||||||
source.minArgumentCount !== target.minArgumentCount ||
|
return Ternary.False;
|
||||||
source.hasRestParameter !== target.hasRestParameter) {
|
|
||||||
if (!partialMatch ||
|
|
||||||
source.parameters.length < target.parameters.length && !source.hasRestParameter ||
|
|
||||||
source.minArgumentCount > target.minArgumentCount) {
|
|
||||||
return Ternary.False;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
let result = Ternary.True;
|
let result = Ternary.True;
|
||||||
if (source.typeParameters && target.typeParameters) {
|
if (source.typeParameters && target.typeParameters) {
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
tests/cases/conformance/types/union/unionTypeCallSignatures4.ts(10,1): error TS2346: Supplied parameters do not match any signature of call target.
|
||||||
|
tests/cases/conformance/types/union/unionTypeCallSignatures4.ts(20,1): error TS2346: Supplied parameters do not match any signature of call target.
|
||||||
|
tests/cases/conformance/types/union/unionTypeCallSignatures4.ts(23,1): error TS2346: Supplied parameters do not match any signature of call target.
|
||||||
|
tests/cases/conformance/types/union/unionTypeCallSignatures4.ts(25,1): error TS2346: Supplied parameters do not match any signature of call target.
|
||||||
|
|
||||||
|
|
||||||
|
==== tests/cases/conformance/types/union/unionTypeCallSignatures4.ts (4 errors) ====
|
||||||
|
type F1 = (a: string, b?: string) => void;
|
||||||
|
type F2 = (a: string, b?: string, c?: string) => void;
|
||||||
|
type F3 = (a: string, ...rest: string[]) => void;
|
||||||
|
type F4 = (a: string, b?: string, ...rest: string[]) => void;
|
||||||
|
type F5 = (a: string, b: string) => void;
|
||||||
|
|
||||||
|
var f12: F1 | F2;
|
||||||
|
f12("a");
|
||||||
|
f12("a", "b");
|
||||||
|
f12("a", "b", "c"); // error
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
!!! error TS2346: Supplied parameters do not match any signature of call target.
|
||||||
|
|
||||||
|
var f34: F3 | F4;
|
||||||
|
f34("a");
|
||||||
|
f34("a", "b");
|
||||||
|
f34("a", "b", "c");
|
||||||
|
|
||||||
|
var f1234: F1 | F2 | F3 | F4;
|
||||||
|
f1234("a");
|
||||||
|
f1234("a", "b");
|
||||||
|
f1234("a", "b", "c"); // error
|
||||||
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
!!! error TS2346: Supplied parameters do not match any signature of call target.
|
||||||
|
|
||||||
|
var f12345: F1 | F2 | F3 | F4 | F5;
|
||||||
|
f12345("a"); // error
|
||||||
|
~~~~~~~~~~~
|
||||||
|
!!! error TS2346: Supplied parameters do not match any signature of call target.
|
||||||
|
f12345("a", "b");
|
||||||
|
f12345("a", "b", "c"); // error
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
!!! error TS2346: Supplied parameters do not match any signature of call target.
|
||||||
|
|
45
tests/baselines/reference/unionTypeCallSignatures4.js
Normal file
45
tests/baselines/reference/unionTypeCallSignatures4.js
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
//// [unionTypeCallSignatures4.ts]
|
||||||
|
type F1 = (a: string, b?: string) => void;
|
||||||
|
type F2 = (a: string, b?: string, c?: string) => void;
|
||||||
|
type F3 = (a: string, ...rest: string[]) => void;
|
||||||
|
type F4 = (a: string, b?: string, ...rest: string[]) => void;
|
||||||
|
type F5 = (a: string, b: string) => void;
|
||||||
|
|
||||||
|
var f12: F1 | F2;
|
||||||
|
f12("a");
|
||||||
|
f12("a", "b");
|
||||||
|
f12("a", "b", "c"); // error
|
||||||
|
|
||||||
|
var f34: F3 | F4;
|
||||||
|
f34("a");
|
||||||
|
f34("a", "b");
|
||||||
|
f34("a", "b", "c");
|
||||||
|
|
||||||
|
var f1234: F1 | F2 | F3 | F4;
|
||||||
|
f1234("a");
|
||||||
|
f1234("a", "b");
|
||||||
|
f1234("a", "b", "c"); // error
|
||||||
|
|
||||||
|
var f12345: F1 | F2 | F3 | F4 | F5;
|
||||||
|
f12345("a"); // error
|
||||||
|
f12345("a", "b");
|
||||||
|
f12345("a", "b", "c"); // error
|
||||||
|
|
||||||
|
|
||||||
|
//// [unionTypeCallSignatures4.js]
|
||||||
|
var f12;
|
||||||
|
f12("a");
|
||||||
|
f12("a", "b");
|
||||||
|
f12("a", "b", "c"); // error
|
||||||
|
var f34;
|
||||||
|
f34("a");
|
||||||
|
f34("a", "b");
|
||||||
|
f34("a", "b", "c");
|
||||||
|
var f1234;
|
||||||
|
f1234("a");
|
||||||
|
f1234("a", "b");
|
||||||
|
f1234("a", "b", "c"); // error
|
||||||
|
var f12345;
|
||||||
|
f12345("a"); // error
|
||||||
|
f12345("a", "b");
|
||||||
|
f12345("a", "b", "c"); // error
|
|
@ -0,0 +1,25 @@
|
||||||
|
type F1 = (a: string, b?: string) => void;
|
||||||
|
type F2 = (a: string, b?: string, c?: string) => void;
|
||||||
|
type F3 = (a: string, ...rest: string[]) => void;
|
||||||
|
type F4 = (a: string, b?: string, ...rest: string[]) => void;
|
||||||
|
type F5 = (a: string, b: string) => void;
|
||||||
|
|
||||||
|
var f12: F1 | F2;
|
||||||
|
f12("a");
|
||||||
|
f12("a", "b");
|
||||||
|
f12("a", "b", "c"); // error
|
||||||
|
|
||||||
|
var f34: F3 | F4;
|
||||||
|
f34("a");
|
||||||
|
f34("a", "b");
|
||||||
|
f34("a", "b", "c");
|
||||||
|
|
||||||
|
var f1234: F1 | F2 | F3 | F4;
|
||||||
|
f1234("a");
|
||||||
|
f1234("a", "b");
|
||||||
|
f1234("a", "b", "c"); // error
|
||||||
|
|
||||||
|
var f12345: F1 | F2 | F3 | F4 | F5;
|
||||||
|
f12345("a"); // error
|
||||||
|
f12345("a", "b");
|
||||||
|
f12345("a", "b", "c"); // error
|
Loading…
Reference in a new issue