@@ -30099,18 +30099,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
30099
30099
isTypeAssignableToKind(checkComputedPropertyName(firstDecl.name), TypeFlags.ESSymbol));
30100
30100
}
30101
30101
30102
- function getObjectLiteralIndexInfo(node: ObjectLiteralExpression, offset: number, properties: Symbol[], keyType: Type): IndexInfo {
30102
+ function getObjectLiteralIndexInfo(offset: number, properties: Symbol[], keyType: Type, isReadonly: boolean ): IndexInfo {
30103
30103
const propTypes: Type[] = [];
30104
30104
for (let i = offset; i < properties.length; i++) {
30105
30105
const prop = properties[i];
30106
- if (keyType === stringType && !isSymbolWithSymbolName(prop) ||
30107
- keyType === numberType && isSymbolWithNumericName(prop) ||
30108
- keyType === esSymbolType && isSymbolWithSymbolName(prop)) {
30106
+ if (keyType === numberType && isSymbolWithNumericName(prop) || keyType === esSymbolType && isSymbolWithSymbolName(prop)) {
30109
30107
propTypes.push(getTypeOfSymbol(properties[i]));
30110
30108
}
30109
+ else if (!isSymbolWithSymbolName(prop)) {
30110
+ if (keyType === stringType) {
30111
+ propTypes.push(getTypeOfSymbol(properties[i]));
30112
+ }
30113
+ else {
30114
+ const source = tryCast(prop, isTransientSymbol)?.links.computedNameType || getStringLiteralType(unescapeLeadingUnderscores(prop.escapedName));
30115
+ if (isTypeAssignableTo(source, keyType)) {
30116
+ propTypes.push(getTypeOfSymbol(properties[i]));
30117
+ }
30118
+ }
30119
+ }
30111
30120
}
30112
30121
const unionType = propTypes.length ? getUnionType(propTypes, UnionReduction.Subtype) : undefinedType;
30113
- return createIndexInfo(keyType, unionType, isConstContext(node) );
30122
+ return createIndexInfo(keyType, unionType, isReadonly );
30114
30123
}
30115
30124
30116
30125
function getImmediateAliasedSymbol(symbol: Symbol): Symbol | undefined {
@@ -30133,6 +30142,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
30133
30142
const allPropertiesTable = strictNullChecks ? createSymbolTable() : undefined;
30134
30143
let propertiesTable = createSymbolTable();
30135
30144
let propertiesArray: Symbol[] = [];
30145
+ let computedNameTypes: Type[] = [];
30136
30146
let spread: Type = emptyObjectType;
30137
30147
30138
30148
pushCachedContextualType(node);
@@ -30191,7 +30201,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
30191
30201
if (nameType) {
30192
30202
prop.links.nameType = nameType;
30193
30203
}
30194
-
30204
+ else if (computedNameType) {
30205
+ prop.links.computedNameType = computedNameType;
30206
+ }
30195
30207
if (inDestructuringPattern) {
30196
30208
// If object literal is an assignment pattern and if the assignment pattern specifies a default value
30197
30209
// for the property, make the property optional.
@@ -30243,6 +30255,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
30243
30255
spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, objectFlags, inConstContext);
30244
30256
propertiesArray = [];
30245
30257
propertiesTable = createSymbolTable();
30258
+ computedNameTypes = [];
30246
30259
hasComputedStringProperty = false;
30247
30260
hasComputedNumberProperty = false;
30248
30261
hasComputedSymbolProperty = false;
@@ -30275,8 +30288,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
30275
30288
checkNodeDeferred(memberDecl);
30276
30289
}
30277
30290
30278
- if (computedNameType && !(computedNameType.flags & TypeFlags.StringOrNumberLiteralOrUnique)) {
30279
- if (isTypeAssignableTo(computedNameType, stringNumberSymbolType)) {
30291
+ if (computedNameType && !isTypeUsableAsPropertyName(computedNameType)) {
30292
+ if (isPatternLiteralType(computedNameType)) {
30293
+ computedNameTypes.push(computedNameType);
30294
+ }
30295
+ else if (isTypeAssignableTo(computedNameType, stringNumberSymbolType)) {
30280
30296
if (isTypeAssignableTo(computedNameType, numberType)) {
30281
30297
hasComputedNumberProperty = true;
30282
30298
}
@@ -30339,6 +30355,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
30339
30355
spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, objectFlags, inConstContext);
30340
30356
propertiesArray = [];
30341
30357
propertiesTable = createSymbolTable();
30358
+ computedNameTypes = [];
30342
30359
hasComputedStringProperty = false;
30343
30360
hasComputedNumberProperty = false;
30344
30361
}
@@ -30349,10 +30366,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
30349
30366
return createObjectLiteralType();
30350
30367
30351
30368
function createObjectLiteralType() {
30352
- const indexInfos = [];
30353
- if (hasComputedStringProperty) indexInfos.push(getObjectLiteralIndexInfo(node, offset, propertiesArray, stringType));
30354
- if (hasComputedNumberProperty) indexInfos.push(getObjectLiteralIndexInfo(node, offset, propertiesArray, numberType));
30355
- if (hasComputedSymbolProperty) indexInfos.push(getObjectLiteralIndexInfo(node, offset, propertiesArray, esSymbolType));
30369
+ let indexInfos: IndexInfo[] = [];
30370
+ for (const computedNameType of computedNameTypes) {
30371
+ const indexInfo = getObjectLiteralIndexInfo(offset, propertiesArray, computedNameType, /*isReadonly*/ inConstContext);
30372
+ indexInfos = appendIndexInfo(indexInfos, indexInfo, /*union*/ true);
30373
+ }
30374
+ if (hasComputedStringProperty) indexInfos.push(getObjectLiteralIndexInfo(offset, propertiesArray, stringType, /*isReadonly*/ inConstContext));
30375
+ if (hasComputedNumberProperty) indexInfos.push(getObjectLiteralIndexInfo(offset, propertiesArray, numberType, /*isReadonly*/ inConstContext));
30376
+ if (hasComputedSymbolProperty) indexInfos.push(getObjectLiteralIndexInfo(offset, propertiesArray, esSymbolType, /*isReadonly*/ inConstContext));
30356
30377
const result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, indexInfos);
30357
30378
result.objectFlags |= objectFlags | ObjectFlags.ObjectLiteral | ObjectFlags.ContainsObjectOrArrayLiteral;
30358
30379
if (isJSObjectLiteral) {
0 commit comments