diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8b10588d376..bac35ab937f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6834,45 +6834,42 @@ namespace ts { return symbol; } + function updateTypeOfMembers(type: Type, update: (propertyType: Type) => Type) { + const members: SymbolTable = {}; + for (const property of getPropertiesOfObjectType(type)) { + const original = getTypeOfSymbol(property); + const updated = update(original); + members[property.name] = updated === original ? property : createTransientSymbol(property, updated); + }; + return members; + } + function getRegularTypeOfObjectLiteral(type: Type): Type { - if (type.flags & TypeFlags.FreshObjectLiteral) { - let regularType = (type).regularType; - if (!regularType) { - regularType = createType((type).flags & ~TypeFlags.FreshObjectLiteral); - regularType.symbol = (type).symbol; - const members: SymbolTable = {}; - const properties: Symbol[] = []; - for (let p of (type).properties) { - const propType = getTypeOfSymbol(p); - if (propType.flags & TypeFlags.FreshObjectLiteral) { - p = createTransientSymbol(p, getRegularTypeOfObjectLiteral(propType)); - } - members[p.name] = p; - properties.push(p); - }; - regularType.properties = properties; - regularType.members = members; - regularType.callSignatures = (type).callSignatures; - regularType.constructSignatures = (type).constructSignatures; - regularType.stringIndexInfo = (type).stringIndexInfo; - regularType.numberIndexInfo = (type).numberIndexInfo; - (type).regularType = regularType; - } + if (!(type.flags & TypeFlags.FreshObjectLiteral)) { + return type; + } + const regularType = (type).regularType; + if (regularType) { return regularType; } - return type; + + const resolved = type; + const members = updateTypeOfMembers(type, prop => prop.flags & TypeFlags.FreshObjectLiteral ? getRegularTypeOfObjectLiteral(prop) : prop); + const regularNew = createAnonymousType(resolved.symbol, + members, + resolved.callSignatures, + resolved.constructSignatures, + resolved.stringIndexInfo, + resolved.numberIndexInfo); + regularNew.flags = resolved.flags & ~TypeFlags.FreshObjectLiteral; + (type).regularType = regularNew; + return regularNew; } function getWidenedTypeOfObjectLiteral(type: Type): Type { - const properties = getPropertiesOfObjectType(type); - const members: SymbolTable = {}; - forEach(properties, p => { - const propType = getTypeOfSymbol(p); - const widenedType = getWidenedType(propType); - if (propType !== widenedType) { - p = createTransientSymbol(p, widenedType); - } - members[p.name] = p; + const members = updateTypeOfMembers(type, prop => { + const widened = getWidenedType(prop); + return prop === widened ? prop : widened; }); const stringIndexInfo = getIndexInfoOfType(type, IndexKind.String); const numberIndexInfo = getIndexInfoOfType(type, IndexKind.Number);