From c5b47fb5c8ce348a4cec1cd52654995052c20cc2 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 29 Oct 2015 14:53:14 -0700 Subject: [PATCH] Correct partial signature matching --- src/compiler/checker.ts | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 99b3d97b7be..1fde2711e12 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5603,18 +5603,29 @@ namespace ts { return compareTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp)); } + // A source signature matches a target signature if the two signatures have the same number of required, + // optional, and rest parameters. + function isMatchingSignature(source: Signature, target: Signature) { + return source.parameters.length === target.parameters.length && + source.minArgumentCount === target.minArgumentCount && + source.hasRestParameter === target.hasRestParameter; + } + + // 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). + function isPartiallyMatchingSignature(source: Signature, target: Signature) { + return source.minArgumentCount <= target.minArgumentCount && ( + source.hasRestParameter && !target.hasRestParameter || + source.hasRestParameter === target.hasRestParameter && source.parameters.length >= target.parameters.length); + } + function compareSignatures(source: Signature, target: Signature, partialMatch: boolean, ignoreReturnTypes: boolean, compareTypes: (s: Type, t: Type) => Ternary): Ternary { if (source === target) { return Ternary.True; } - if (source.parameters.length !== target.parameters.length || - source.minArgumentCount !== target.minArgumentCount || - source.hasRestParameter !== target.hasRestParameter) { - if (!partialMatch || - source.parameters.length < target.parameters.length && !source.hasRestParameter || - source.minArgumentCount > target.minArgumentCount) { - return Ternary.False; - } + if (!(isMatchingSignature(source, target) || partialMatch && isPartiallyMatchingSignature(source, target))) { + return Ternary.False; } let result = Ternary.True; if (source.typeParameters && target.typeParameters) {