From a163641bd3570a90fa6b09cc2a373a64bad5e679 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 28 Oct 2016 08:57:19 -0700 Subject: [PATCH] isAritySmaller runs later: getNonGenericSignature --- src/compiler/checker.ts | 48 +++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 28 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8748fd6db95..14c05d93246 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10299,16 +10299,32 @@ namespace ts { // If the given type is an object or union type, if that type has a single signature, and if // that signature is non-generic, return the signature. Otherwise return undefined. - function getNonGenericSignature(type: Type): Signature { + function getNonGenericSignature(type: Type, node: FunctionExpression | ArrowFunction | MethodDeclaration): Signature { const signatures = getSignaturesOfStructuredType(type, SignatureKind.Call); if (signatures.length === 1) { const signature = signatures[0]; - if (!signature.typeParameters) { + if (!signature.typeParameters && !isAritySmaller(signature, node)) { return signature; } } } + /** If the contextual signature has fewer parameters than the function expression, do not use it */ + function isAritySmaller(signature: Signature, target: FunctionExpression | ArrowFunction | MethodDeclaration) { + let targetParameterCount = 0; + for (; targetParameterCount < target.parameters.length; targetParameterCount++) { + const param = target.parameters[targetParameterCount]; + if (param.initializer || param.questionToken || param.dotDotDotToken || isJSDocOptionalParameter(param)) { + break; + } + } + if (target.parameters.length && parameterIsThisKeyword(target.parameters[0])) { + targetParameterCount--; + } + const sourceLength = signature.hasRestParameter ? Number.MAX_VALUE : signature.parameters.length; + return sourceLength < targetParameterCount; + } + function isFunctionExpressionOrArrowFunction(node: Node): node is FunctionExpression | ArrowFunction { return node.kind === SyntaxKind.FunctionExpression || node.kind === SyntaxKind.ArrowFunction; } @@ -10337,17 +10353,13 @@ namespace ts { if (!type) { return undefined; } - // If the contextual signature has fewer parameters than the function expression, do not use it - if (isFunctionExpressionOrArrowFunction(node) && isAritySmaller(type, node)) { - return undefined; - } if (!(type.flags & TypeFlags.Union)) { - return getNonGenericSignature(type); + return getNonGenericSignature(type, node); } let signatureList: Signature[]; const types = (type).types; for (const current of types) { - const signature = getNonGenericSignature(current); + const signature = getNonGenericSignature(current, node); if (signature) { if (!signatureList) { // This signature will contribute to contextual union signature @@ -10375,26 +10387,6 @@ namespace ts { return result; } - function isAritySmaller(sourceType: Type, target: FunctionExpression | ArrowFunction) { - if (isFunctionType(sourceType)) { - let targetParameterCount = 0; - for (; targetParameterCount < target.parameters.length; targetParameterCount++) { - const param = target.parameters[targetParameterCount]; - if (param.initializer || param.questionToken || param.dotDotDotToken || isJSDocOptionalParameter(param)) { - break; - } - } - if (target.parameters.length && parameterIsThisKeyword(target.parameters[0])) { - targetParameterCount--; - } - const sourceSignatures = getSignaturesOfType(sourceType, SignatureKind.Call); - const sourceLengths = sourceSignatures.map(sig => !sig.hasRestParameter ? sig.parameters.length : Number.MAX_VALUE); - return forEach(sourceLengths, len => len < targetParameterCount); - } - - return false; - } - /** * Detect if the mapper implies an inference context. Specifically, there are 4 possible values * for a mapper. Let's go through each one of them: