diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3e64493503c42..75246fa7cfa1a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -18565,7 +18565,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (everyType(objectType, isTupleType) && isNumericLiteralName(propName)) { const index = +propName; - if (accessNode && everyType(objectType, t => !(t as TupleTypeReference).target.hasRestElement) && !(accessFlags & AccessFlags.NoTupleBoundsCheck)) { + if (accessNode && everyType(objectType, t => !((t as TupleTypeReference).target.combinedFlags & ElementFlags.Variable)) && !(accessFlags & AccessFlags.NoTupleBoundsCheck)) { const indexNode = getIndexNodeForAccessExpression(accessNode); if (isTupleType(objectType)) { if (index < 0) { @@ -25753,7 +25753,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function tupleTypesDefinitelyUnrelated(source: TupleTypeReference, target: TupleTypeReference) { return !(target.target.combinedFlags & ElementFlags.Variadic) && target.target.minLength > source.target.minLength || - !target.target.hasRestElement && (source.target.hasRestElement || target.target.fixedLength < source.target.fixedLength); + !(target.target.combinedFlags & ElementFlags.Variable) && (!!(source.target.combinedFlags & ElementFlags.Variable) || target.target.fixedLength < source.target.fixedLength); } function typesDefinitelyUnrelated(source: Type, target: Type) { @@ -26584,7 +26584,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return; } const startLength = isTupleType(source) ? Math.min(source.target.fixedLength, target.target.fixedLength) : 0; - const endLength = Math.min(isTupleType(source) ? getEndElementCount(source.target, ElementFlags.Fixed) : 0, target.target.hasRestElement ? getEndElementCount(target.target, ElementFlags.Fixed) : 0); + const endLength = Math.min(isTupleType(source) ? getEndElementCount(source.target, ElementFlags.Fixed) : 0, target.target.combinedFlags & ElementFlags.Variable ? getEndElementCount(target.target, ElementFlags.Fixed) : 0); // Infer between starting fixed elements. for (let i = 0; i < startLength; i++) { inferFromTypes(getTypeArguments(source)[i], elementTypes[i]); @@ -26613,7 +26613,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // if T is constrained by a fixed-size tuple we might be able to use its arity to infer T const param = getInferenceInfoForType(elementTypes[startLength])?.typeParameter; const constraint = param && getBaseConstraintOfType(param); - if (constraint && isTupleType(constraint) && !constraint.target.hasRestElement) { + if (constraint && isTupleType(constraint) && !(constraint.target.combinedFlags & ElementFlags.Variable)) { const impliedArity = constraint.target.fixedLength; inferFromTypes(sliceTupleType(source, startLength, sourceArity - (startLength + impliedArity)), elementTypes[startLength]); inferFromTypes(getElementTypeOfSliceOfTupleType(source, startLength + impliedArity, endLength)!, elementTypes[startLength + 1]); @@ -26624,7 +26624,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // if T is constrained by a fixed-size tuple we might be able to use its arity to infer T const param = getInferenceInfoForType(elementTypes[startLength + 1])?.typeParameter; const constraint = param && getBaseConstraintOfType(param); - if (constraint && isTupleType(constraint) && !constraint.target.hasRestElement) { + if (constraint && isTupleType(constraint) && !(constraint.target.combinedFlags & ElementFlags.Variable)) { const impliedArity = constraint.target.fixedLength; const endIndex = sourceArity - getEndElementCount(target.target, ElementFlags.Fixed); const startIndex = endIndex - impliedArity; @@ -31579,7 +31579,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // When the length is known and the index is after all spread elements we compute the offset from the element // to the end and the number of ending fixed elements in the contextual tuple type. const offset = length !== undefined && (lastSpreadIndex === undefined || index > lastSpreadIndex) ? length - index : 0; - const fixedEndLength = offset > 0 && t.target.hasRestElement ? getEndElementCount(t.target, ElementFlags.Fixed) : 0; + const fixedEndLength = offset > 0 && (t.target.combinedFlags & ElementFlags.Variable) ? getEndElementCount(t.target, ElementFlags.Fixed) : 0; // If the offset is within the ending fixed part of the contextual tuple type, return the type of the contextual // tuple element. if (offset > 0 && offset <= fixedEndLength) { @@ -37363,7 +37363,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // otherwise would return the type 'undefined'). const restType = getTypeOfSymbol(signature.parameters[paramCount]); const index = pos - paramCount; - if (!isTupleType(restType) || restType.target.hasRestElement || index < restType.target.fixedLength) { + if (!isTupleType(restType) || restType.target.combinedFlags & ElementFlags.Variable || index < restType.target.fixedLength) { return getIndexedAccessType(restType, getNumberLiteralType(index)); } } @@ -37412,7 +37412,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (signatureHasRestParameter(signature)) { const restType = getTypeOfSymbol(signature.parameters[length - 1]); if (isTupleType(restType)) { - return length + restType.target.fixedLength - (restType.target.hasRestElement ? 0 : 1); + return length + restType.target.fixedLength - (restType.target.combinedFlags & ElementFlags.Variable ? 0 : 1); } } return length; @@ -37457,7 +37457,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function hasEffectiveRestParameter(signature: Signature) { if (signatureHasRestParameter(signature)) { const restType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]); - return !isTupleType(restType) || restType.target.hasRestElement; + return !isTupleType(restType) || !!(restType.target.combinedFlags & ElementFlags.Variable); } return false; } @@ -37468,7 +37468,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!isTupleType(restType)) { return isTypeAny(restType) ? anyArrayType : restType; } - if (restType.target.hasRestElement) { + if (restType.target.combinedFlags & ElementFlags.Variable) { return sliceTupleType(restType, restType.target.fixedLength); } } @@ -40143,7 +40143,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { checkExpressionWithContextualType(initializer, contextualType, /*inferenceContext*/ undefined, checkMode || CheckMode.Normal) : checkExpressionCached(initializer, checkMode)); return isParameter(declaration) && declaration.name.kind === SyntaxKind.ArrayBindingPattern && - isTupleType(type) && !type.target.hasRestElement && getTypeReferenceArity(type) < declaration.name.elements.length ? + isTupleType(type) && !(type.target.combinedFlags & ElementFlags.Variable) && getTypeReferenceArity(type) < declaration.name.elements.length ? padTupleType(type, declaration.name) : type; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 083f260b6e192..542735b596885 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -6510,7 +6510,11 @@ export interface TupleType extends GenericType { minLength: number; /** Number of initial required or optional elements */ fixedLength: number; - /** True if tuple has any rest or variadic elements */ + /** + * True if tuple has any rest or variadic elements + * + * @deprecated Use `.combinedFlags & ElementFlags.Variable` instead + */ hasRestElement: boolean; combinedFlags: ElementFlags; readonly: boolean; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index ef65f57a8cd13..c5712e941d1c8 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -6665,7 +6665,11 @@ declare namespace ts { minLength: number; /** Number of initial required or optional elements */ fixedLength: number; - /** True if tuple has any rest or variadic elements */ + /** + * True if tuple has any rest or variadic elements + * + * @deprecated Use `.combinedFlags & ElementFlags.Variable` instead + */ hasRestElement: boolean; combinedFlags: ElementFlags; readonly: boolean;