mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 08:11:30 -06:00
Fix excess property checking in array destructuring contexts
Co-authored-by: RyanCavanaugh <6685088+RyanCavanaugh@users.noreply.github.com>
This commit is contained in:
parent
5d148fdce6
commit
14850044d4
@ -36065,12 +36065,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
const arg = args[i];
|
||||
if (arg.kind !== SyntaxKind.OmittedExpression) {
|
||||
const paramType = getTypeAtPosition(signature, i);
|
||||
const argType = checkExpressionWithContextualType(arg, paramType, /*inferenceContext*/ undefined, checkMode);
|
||||
// If one or more arguments are still excluded (as indicated by CheckMode.SkipContextSensitive),
|
||||
// we obtain the regular type of any object literal arguments because we may not have inferred complete
|
||||
// parameter types yet and therefore excess property checks may yield false positives (see #17041).
|
||||
const checkArgType = checkMode & CheckMode.SkipContextSensitive ? getRegularTypeOfObjectLiteral(argType) : argType;
|
||||
const effectiveCheckArgumentNode = getEffectiveCheckNode(arg);
|
||||
const argType = checkExpressionWithContextualType(arg, paramType, /*inferenceContext*/ undefined, checkMode);
|
||||
// If one or more arguments are still excluded (as indicated by CheckMode.SkipContextSensitive),
|
||||
// we obtain the regular type of any object literal arguments because we may not have inferred complete
|
||||
// parameter types yet and therefore excess property checks may yield false positives (see #17041).
|
||||
// Also skip fresh literal checking when the call is in a destructuring context to avoid inappropriate
|
||||
// excess property checking (see #41548).
|
||||
const shouldSkipFreshness = (checkMode & CheckMode.SkipContextSensitive) ||
|
||||
(isCallExpression(node) && isCallInDestructuringContext(node));
|
||||
const checkArgType = shouldSkipFreshness ? getRegularTypeOfObjectLiteral(argType) : argType;
|
||||
const effectiveCheckArgumentNode = getEffectiveCheckNode(arg);
|
||||
if (!checkTypeRelatedToAndOptionallyElaborate(checkArgType, paramType, relation, reportErrors ? effectiveCheckArgumentNode : undefined, effectiveCheckArgumentNode, headMessage, containingMessageChain, errorOutputContainer)) {
|
||||
Debug.assert(!reportErrors || !!errorOutputContainer.errors, "parameter should have errors when reporting errors");
|
||||
maybeAddMissingAwaitInfo(arg, checkArgType, paramType);
|
||||
@ -36415,8 +36419,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return createDiagnosticForNodeArrayFromMessageChain(getSourceFileOfNode(node), typeArguments, chain);
|
||||
}
|
||||
return createDiagnosticForNodeArray(getSourceFileOfNode(node), typeArguments, Diagnostics.Expected_0_type_arguments_but_got_1, belowArgCount === -Infinity ? aboveArgCount : belowArgCount, argCount);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function isCallInDestructuringContext(node: CallLikeExpression): boolean {
|
||||
// Check if this call expression is used as the initializer in a variable declaration with a destructuring pattern
|
||||
const parent = node.parent;
|
||||
if (parent && isVariableDeclaration(parent) && parent.initializer === node) {
|
||||
return isBindingPattern(parent.name);
|
||||
}
|
||||
|
||||
// Check for assignment expressions: [a, b] = foo()
|
||||
if (parent && isBinaryExpression(parent) && parent.operatorToken.kind === SyntaxKind.EqualsToken && parent.right === node) {
|
||||
return isArrayLiteralExpression(parent.left) || isObjectLiteralExpression(parent.left);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function resolveCall(node: CallLikeExpression, signatures: readonly Signature[], candidatesOutArray: Signature[] | undefined, checkMode: CheckMode, callChainFlags: SignatureFlags, headMessage?: DiagnosticMessage): Signature {
|
||||
const isTaggedTemplate = node.kind === SyntaxKind.TaggedTemplateExpression;
|
||||
const isDecorator = node.kind === SyntaxKind.Decorator;
|
||||
@ -36488,9 +36507,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
//
|
||||
// For a decorator, no arguments are susceptible to contextual typing due to the fact
|
||||
// decorators are applied to a declaration by the emitter, and not to an expression.
|
||||
const isSingleNonGenericCandidate = candidates.length === 1 && !candidates[0].typeParameters;
|
||||
if (!isDecorator && !isSingleNonGenericCandidate && some(args, isContextSensitive)) {
|
||||
argCheckMode = CheckMode.SkipContextSensitive;
|
||||
const isSingleNonGenericCandidate = candidates.length === 1 && !candidates[0].typeParameters;
|
||||
let shouldSkipContextSensitive = !isDecorator && !isSingleNonGenericCandidate && some(args, isContextSensitive);
|
||||
|
||||
// Also skip context sensitive checking when the call is used in a destructuring context
|
||||
// to avoid inappropriate excess property checking on object literal arguments
|
||||
const isInDestructuring = !isDecorator && isCallInDestructuringContext(node);
|
||||
if (isInDestructuring && !shouldSkipContextSensitive) {
|
||||
shouldSkipContextSensitive = true;
|
||||
}
|
||||
|
||||
if (shouldSkipContextSensitive) {
|
||||
argCheckMode = CheckMode.SkipContextSensitive;
|
||||
}
|
||||
|
||||
// If we are in signature help, a trailing comma indicates that we intend to provide another argument,
|
||||
@ -36678,7 +36706,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
if (some(typeArguments) || !hasCorrectArity(node, args, candidate, signatureHelpTrailingComma)) {
|
||||
return undefined;
|
||||
}
|
||||
if (getSignatureApplicabilityError(node, args, candidate, relation, CheckMode.Normal, /*reportErrors*/ false, /*containingMessageChain*/ undefined)) {
|
||||
if (getSignatureApplicabilityError(node, args, candidate, relation, argCheckMode, /*reportErrors*/ false, /*containingMessageChain*/ undefined)) {
|
||||
candidatesForArgumentError = [candidate];
|
||||
return undefined;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user