Skip overloads with too-short function parameters
If the parameter of an overload is a function and the argument is also a function, skip the overload if the parameter has fewer arguments than the argument does. That overload cannot possibly apply, and should not participate in, for example, contextual typing. Example: ```ts interface I { (a: number): void; (b: string, c): void; } declare function f(i: I): void; f((x, y) => {}); ``` This code now skips the first overload instead of considering. This was a longstanding bug but was only uncovered now that more functions expressions are context sensitive.
This commit is contained in:
parent
f307948af0
commit
83fdecf86a
|
@ -11890,6 +11890,11 @@ namespace ts {
|
|||
// If the effective argument type is 'undefined', there is no synthetic type
|
||||
// for the argument. In that case, we should check the argument.
|
||||
if (argType === undefined) {
|
||||
// If the parameter and argument are both functions and the parameter has fewer arguments than the argument,
|
||||
// then this signature is not applicable. Exit early.
|
||||
if (!reportErrors && isAritySmaller(paramType, arg)) {
|
||||
return false;
|
||||
}
|
||||
argType = checkExpressionWithContextualType(arg, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined);
|
||||
}
|
||||
|
||||
|
@ -11904,6 +11909,21 @@ namespace ts {
|
|||
return true;
|
||||
}
|
||||
|
||||
function isAritySmaller(sourceType: Type, target: Expression) {
|
||||
if (isFunctionExpressionOrArrowFunction(target) && 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;
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the this argument in calls like x.f(...) and x[f](...). Undefined otherwise.
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue