diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 94e9fd30a79..955dacfbb89 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10145,6 +10145,11 @@ namespace ts { if (objectType === wildcardType || indexType === wildcardType) { return wildcardType; } + // If the object type has a string index signature and no other members we know that the result will + // always be the type of that index signature and we can simplify accordingly. + if (isStringIndexSignatureOnlyType(objectType) && !(indexType.flags & TypeFlags.Nullable) && isTypeAssignableToKind(indexType, TypeFlags.String | TypeFlags.Number)) { + indexType = stringType; + } // If the index type is generic, or if the object type is generic and doesn't originate in an expression, // we are performing a higher-order index access where we cannot meaningfully access the properties of the // object type. Note that for a generic T and a non-generic K, we eagerly resolve T[K] if it originates in @@ -12022,6 +12027,12 @@ namespace ts { return !!(getObjectFlags(type) & ObjectFlags.Anonymous) && isEmptyObjectType(type); } + function isStringIndexSignatureOnlyType(type: Type): boolean { + return type.flags & TypeFlags.Object && getPropertiesOfType(type).length === 0 && getIndexInfoOfType(type, IndexKind.String) && !getIndexInfoOfType(type, IndexKind.Number) || + type.flags & TypeFlags.UnionOrIntersection && every((type).types, isStringIndexSignatureOnlyType) || + false; + } + function isEnumTypeRelatedTo(sourceSymbol: Symbol, targetSymbol: Symbol, errorReporter?: ErrorReporter) { if (sourceSymbol === targetSymbol) { return true;