@@ -14551,11 +14551,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1455114551 }
1455214552
1455314553 function getResolvedApparentTypeOfMappedType(type: MappedType) {
14554- const typeVariable = getHomomorphicTypeVariable(type);
14555- if (typeVariable && !type.declaration.nameType) {
14556- const constraint = getConstraintOfTypeParameter(typeVariable);
14557- if (constraint && everyType(constraint, isArrayOrTupleType)) {
14558- return instantiateType(type, prependTypeMapping(typeVariable, constraint, type.mapper));
14554+ const target = (type.target ?? type) as MappedType;
14555+ const typeVariable = getHomomorphicTypeVariable(target);
14556+ if (typeVariable && !target.declaration.nameType) {
14557+ const constraint = getConstraintTypeFromMappedType(type);
14558+ if (constraint.flags & TypeFlags.Index) {
14559+ const baseConstraint = getBaseConstraintOfType((constraint as IndexType).type);
14560+ if (baseConstraint && everyType(baseConstraint, isArrayOrTupleType)) {
14561+ return instantiateType(target, prependTypeMapping(typeVariable, baseConstraint, type.mapper));
14562+ }
1455914563 }
1456014564 }
1456114565 return type;
@@ -20820,8 +20824,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2082020824 const restIndex = sourceRestType || targetRestType ? paramCount - 1 : -1;
2082120825
2082220826 for (let i = 0; i < paramCount; i++) {
20823- const sourceType = i === restIndex ? getRestTypeAtPosition (source, i) : tryGetTypeAtPosition(source, i);
20824- const targetType = i === restIndex ? getRestTypeAtPosition (target, i) : tryGetTypeAtPosition(target, i);
20827+ const sourceType = i === restIndex ? getRestOrAnyTypeAtPosition (source, i) : tryGetTypeAtPosition(source, i);
20828+ const targetType = i === restIndex ? getRestOrAnyTypeAtPosition (target, i) : tryGetTypeAtPosition(target, i);
2082520829 if (sourceType && targetType) {
2082620830 // In order to ensure that any generic type Foo<T> is at least co-variant with respect to T no matter
2082720831 // how Foo uses T, we need to relate parameters bi-variantly (given that parameters are input positions,
@@ -36447,6 +36451,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3644736451 return createTupleType(types, flags, readonly, names);
3644836452 }
3644936453
36454+ // Return the rest type at the given position, transforming `any[]` into just `any`. We do this because
36455+ // in signatures we want `any[]` in a rest position to be compatible with anything, but `any[]` isn't
36456+ // assignable to tuple types with required elements.
36457+ function getRestOrAnyTypeAtPosition(source: Signature, pos: number): Type {
36458+ const restType = getRestTypeAtPosition(source, pos);
36459+ const elementType = restType && getElementTypeOfArrayType(restType);
36460+ return elementType && isTypeAny(elementType) ? anyType : restType;
36461+ }
36462+
3645036463 // Return the number of parameters in a signature. The rest parameter, if present, counts as one
3645136464 // parameter. For example, the parameter count of (x: number, y: number, ...z: string[]) is 3 and
3645236465 // the parameter count of (x: number, ...args: [number, ...string[], boolean])) is also 3. In the
@@ -36510,7 +36523,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3651036523 if (signatureHasRestParameter(signature)) {
3651136524 const restType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]);
3651236525 if (!isTupleType(restType)) {
36513- return restType;
36526+ return isTypeAny(restType) ? anyArrayType : restType;
3651436527 }
3651536528 if (restType.target.hasRestElement) {
3651636529 return sliceTupleType(restType, restType.target.fixedLength);
@@ -40510,7 +40523,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4051040523 const objectIndexType = isGenericMappedType(objectType) && getMappedTypeNameTypeKind(objectType) === MappedTypeNameTypeKind.Remapping
4051140524 ? getIndexTypeForMappedType(objectType, IndexFlags.None)
4051240525 : getIndexType(objectType, IndexFlags.None);
40513- if (isTypeAssignableTo(indexType, objectIndexType)) {
40526+ const hasNumberIndexInfo = !!getIndexInfoOfType(objectType, numberType);
40527+ if (everyType(indexType, t => isTypeAssignableTo(t, objectIndexType) || hasNumberIndexInfo && isApplicableIndexType(t, numberType))) {
4051440528 if (
4051540529 accessNode.kind === SyntaxKind.ElementAccessExpression && isAssignmentTarget(accessNode) &&
4051640530 getObjectFlags(objectType) & ObjectFlags.Mapped && getMappedTypeModifiers(objectType as MappedType) & MappedTypeModifiers.IncludeReadonly
@@ -40519,16 +40533,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4051940533 }
4052040534 return type;
4052140535 }
40522- // Check if we're indexing with a numeric type and if either object or index types
40523- // is a generic type with a constraint that has a numeric index signature.
40524- const apparentObjectType = getApparentType(objectType);
40525- if (getIndexInfoOfType(apparentObjectType, numberType) && isTypeAssignableToKind(indexType, TypeFlags.NumberLike)) {
40526- return type;
40527- }
4052840536 if (isGenericObjectType(objectType)) {
4052940537 const propertyName = getPropertyNameFromIndex(indexType, accessNode);
4053040538 if (propertyName) {
40531- const propertySymbol = forEachType(apparentObjectType , t => getPropertyOfType(t, propertyName));
40539+ const propertySymbol = forEachType(getApparentType(objectType) , t => getPropertyOfType(t, propertyName));
4053240540 if (propertySymbol && getDeclarationModifierFlagsFromSymbol(propertySymbol) & ModifierFlags.NonPublicAccessibilityModifier) {
4053340541 error(accessNode, Diagnostics.Private_or_protected_member_0_cannot_be_accessed_on_a_type_parameter, unescapeLeadingUnderscores(propertyName));
4053440542 return errorType;
0 commit comments