@@ -5280,17 +5280,18 @@ namespace ts {
52805280 let objectFlags = ObjectFlags.ObjectLiteral;
52815281 forEach(pattern.elements, e => {
52825282 const name = e.propertyName || <Identifier>e.name;
5283- if (isComputedNonLiteralName(name)) {
5284- // do not include computed properties in the implied type
5285- objectFlags |= ObjectFlags.ObjectLiteralPatternWithComputedProperties;
5286- return;
5287- }
52885283 if (e.dotDotDotToken) {
52895284 stringIndexInfo = createIndexInfo(anyType, /*isReadonly*/ false);
52905285 return;
52915286 }
52925287
5293- const text = getTextOfPropertyName(name);
5288+ const exprType = getLiteralTypeFromPropertyName(name);
5289+ if (!isTypeUsableAsPropertyName(exprType)) {
5290+ // do not include computed properties in the implied type
5291+ objectFlags |= ObjectFlags.ObjectLiteralPatternWithComputedProperties;
5292+ return;
5293+ }
5294+ const text = getPropertyNameFromType(exprType);
52945295 const flags = SymbolFlags.Property | (e.initializer ? SymbolFlags.Optional : 0);
52955296 const symbol = createSymbol(flags, text);
52965297 symbol.type = getTypeFromBindingElement(e, includePatternInType, reportErrors);
@@ -6399,9 +6400,9 @@ namespace ts {
63996400 }
64006401
64016402 /**
6402- * Indicates whether a type can be used as a late-bound name.
6403+ * Indicates whether a type can be used as a property name.
64036404 */
6404- function isTypeUsableAsLateBoundName (type: Type): type is LiteralType | UniqueESSymbolType {
6405+ function isTypeUsableAsPropertyName (type: Type): type is StringLiteralType | NumberLiteralType | UniqueESSymbolType {
64056406 return !!(type.flags & TypeFlags.StringOrNumberLiteralOrUnique);
64066407 }
64076408
@@ -6416,7 +6417,7 @@ namespace ts {
64166417 function isLateBindableName(node: DeclarationName): node is LateBoundName {
64176418 return isComputedPropertyName(node)
64186419 && isEntityNameExpression(node.expression)
6419- && isTypeUsableAsLateBoundName (checkComputedPropertyName(node));
6420+ && isTypeUsableAsPropertyName (checkComputedPropertyName(node));
64206421 }
64216422
64226423 function isLateBoundName(name: __String): boolean {
@@ -6448,11 +6449,11 @@ namespace ts {
64486449 }
64496450
64506451 /**
6451- * Gets the symbolic name for a late-bound member from its type.
6452+ * Gets the symbolic name for a member from its type.
64526453 */
6453- function getLateBoundNameFromType (type: StringLiteralType | NumberLiteralType | UniqueESSymbolType): __String {
6454+ function getPropertyNameFromType (type: StringLiteralType | NumberLiteralType | UniqueESSymbolType): __String {
64546455 if (type.flags & TypeFlags.UniqueESSymbol) {
6455- return `__@${type.symbol.escapedName}@${getSymbolId( type.symbol)}` as __String ;
6456+ return (<UniqueESSymbolType> type).escapedName ;
64566457 }
64576458 if (type.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral)) {
64586459 return escapeLeadingUnderscores("" + (<StringLiteralType | NumberLiteralType>type).value);
@@ -6518,8 +6519,8 @@ namespace ts {
65186519 // fall back to the early-bound name of this member.
65196520 links.resolvedSymbol = decl.symbol;
65206521 const type = checkComputedPropertyName(decl.name);
6521- if (isTypeUsableAsLateBoundName (type)) {
6522- const memberName = getLateBoundNameFromType (type);
6522+ if (isTypeUsableAsPropertyName (type)) {
6523+ const memberName = getPropertyNameFromType (type);
65236524 const symbolFlags = decl.symbol.flags;
65246525
65256526 // Get or add a late-bound symbol for the member. This allows us to merge late-bound accessor declarations.
@@ -7168,8 +7169,8 @@ namespace ts {
71687169 const propType = instantiateType(templateType, templateMapper);
71697170 // If the current iteration type constituent is a string literal type, create a property.
71707171 // Otherwise, for type string create a string index signature.
7171- if (t.flags & TypeFlags.StringOrNumberLiteralOrUnique ) {
7172- const propName = getLateBoundNameFromType(t as LiteralType );
7172+ if (isTypeUsableAsPropertyName(t) ) {
7173+ const propName = getPropertyNameFromType(t );
71737174 const modifiersProp = getPropertyOfType(modifiersType, propName);
71747175 const isOptional = !!(templateModifiers & MappedTypeModifiers.IncludeOptional ||
71757176 !(templateModifiers & MappedTypeModifiers.ExcludeOptional) && modifiersProp && modifiersProp.flags & SymbolFlags.Optional);
@@ -7354,7 +7355,8 @@ namespace ts {
73547355 function isTypeInvalidDueToUnionDiscriminant(contextualType: Type, obj: ObjectLiteralExpression | JsxAttributes): boolean {
73557356 const list = obj.properties as NodeArray<ObjectLiteralElementLike | JsxAttributeLike>;
73567357 return list.some(property => {
7357- const name = property.name && getTextOfPropertyName(property.name);
7358+ const nameType = property.name && getLiteralTypeFromPropertyName(property.name);
7359+ const name = nameType && isTypeUsableAsPropertyName(nameType) ? getPropertyNameFromType(nameType) : undefined;
73587360 const expected = name === undefined ? undefined : getTypeOfPropertyOfType(contextualType, name);
73597361 return !!expected && isLiteralType(expected) && !isTypeIdenticalTo(getTypeOfNode(property), expected);
73607362 });
@@ -9722,8 +9724,8 @@ namespace ts {
97229724
97239725 function getPropertyTypeForIndexType(objectType: Type, indexType: Type, accessNode: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression | undefined, cacheSymbol: boolean, missingType: Type) {
97249726 const accessExpression = accessNode && accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode : undefined;
9725- const propName = isTypeUsableAsLateBoundName (indexType) ?
9726- getLateBoundNameFromType (indexType) :
9727+ const propName = isTypeUsableAsPropertyName (indexType) ?
9728+ getPropertyNameFromType (indexType) :
97279729 accessExpression && checkThatExpressionIsProperSymbolReference(accessExpression.argumentExpression, indexType, /*reportError*/ false) ?
97289730 getPropertyNameForKnownSymbolName(idText((<PropertyAccessExpression>accessExpression.argumentExpression).name)) :
97299731 accessNode && isPropertyName(accessNode) ?
@@ -10413,6 +10415,7 @@ namespace ts {
1041310415 function createUniqueESSymbolType(symbol: Symbol) {
1041410416 const type = <UniqueESSymbolType>createType(TypeFlags.UniqueESSymbol);
1041510417 type.symbol = symbol;
10418+ type.escapedName = `__@${type.symbol.escapedName}@${getSymbolId(type.symbol)}` as __String;
1041610419 return type;
1041710420 }
1041810421
@@ -11300,7 +11303,7 @@ namespace ts {
1130011303 }
1130111304 if (resultObj.error) {
1130211305 const reportedDiag = resultObj.error;
11303- const propertyName = isTypeUsableAsLateBoundName (nameType) ? getLateBoundNameFromType (nameType) : undefined;
11306+ const propertyName = isTypeUsableAsPropertyName (nameType) ? getPropertyNameFromType (nameType) : undefined;
1130411307 const targetProp = propertyName !== undefined ? getPropertyOfType(target, propertyName) : undefined;
1130511308
1130611309 let issuedElaboration = false;
@@ -15172,7 +15175,9 @@ namespace ts {
1517215175 }
1517315176
1517415177 function getTypeOfDestructuredProperty(type: Type, name: PropertyName) {
15175- const text = getTextOfPropertyName(name);
15178+ const nameType = getLiteralTypeFromPropertyName(name);
15179+ if (!isTypeUsableAsPropertyName(nameType)) return errorType;
15180+ const text = getPropertyNameFromType(nameType);
1517615181 return getConstraintForLocation(getTypeOfPropertyOfType(type, text), name) ||
1517715182 isNumericLiteralName(text) && getIndexTypeOfType(type, IndexKind.Number) ||
1517815183 getIndexTypeOfType(type, IndexKind.String) ||
@@ -17304,9 +17309,10 @@ namespace ts {
1730417309 const parentDeclaration = declaration.parent.parent;
1730517310 const name = declaration.propertyName || declaration.name;
1730617311 const parentType = getContextualTypeForVariableLikeDeclaration(parentDeclaration);
17307- if (parentType && !isBindingPattern(name)) {
17308- const text = getTextOfPropertyName(name);
17309- if (text !== undefined) {
17312+ if (parentType && !isBindingPattern(name) && !isComputedNonLiteralName(name)) {
17313+ const nameType = getLiteralTypeFromPropertyName(name);
17314+ if (isTypeUsableAsPropertyName(nameType)) {
17315+ const text = getPropertyNameFromType(nameType);
1731017316 return getTypeOfPropertyOfType(parentType, text);
1731117317 }
1731217318 }
@@ -18263,10 +18269,9 @@ namespace ts {
1826318269 }
1826418270 }
1826518271 typeFlags |= type.flags;
18266- const nameType = computedNameType && computedNameType.flags & TypeFlags.StringOrNumberLiteralOrUnique ?
18267- <LiteralType | UniqueESSymbolType>computedNameType : undefined;
18272+ const nameType = computedNameType && isTypeUsableAsPropertyName(computedNameType) ? computedNameType : undefined;
1826818273 const prop = nameType ?
18269- createSymbol(SymbolFlags.Property | member.flags, getLateBoundNameFromType (nameType), CheckFlags.Late) :
18274+ createSymbol(SymbolFlags.Property | member.flags, getPropertyNameFromType (nameType), CheckFlags.Late) :
1827018275 createSymbol(SymbolFlags.Property | member.flags, member.escapedName);
1827118276 if (nameType) {
1827218277 prop.nameType = nameType;
@@ -22315,15 +22320,15 @@ namespace ts {
2231522320 function checkObjectLiteralDestructuringPropertyAssignment(objectLiteralType: Type, property: ObjectLiteralElementLike, allProperties?: NodeArray<ObjectLiteralElementLike>, rightIsThis = false) {
2231622321 if (property.kind === SyntaxKind.PropertyAssignment || property.kind === SyntaxKind.ShorthandPropertyAssignment) {
2231722322 const name = property.name;
22318- const text = getTextOfPropertyName(name);
22319- if (text) {
22323+ const exprType = getLiteralTypeFromPropertyName(name);
22324+ if (isTypeUsableAsPropertyName(exprType)) {
22325+ const text = getPropertyNameFromType(exprType);
2232022326 const prop = getPropertyOfType(objectLiteralType, text);
2232122327 if (prop) {
2232222328 markPropertyAsReferenced(prop, property, rightIsThis);
2232322329 checkPropertyAccessibility(property, /*isSuper*/ false, objectLiteralType, prop);
2232422330 }
2232522331 }
22326- const exprType = getLiteralTypeFromPropertyName(name);
2232722332 const elementType = getIndexedAccessType(objectLiteralType, exprType, name);
2232822333 const type = getFlowTypeOfDestructuring(property, elementType);
2232922334 return checkDestructuringAssignment(property.kind === SyntaxKind.ShorthandPropertyAssignment ? property : property.initializer, type);
@@ -25638,13 +25643,14 @@ namespace ts {
2563825643 const parent = node.parent.parent;
2563925644 const parentType = getTypeForBindingElementParent(parent);
2564025645 const name = node.propertyName || node.name;
25641- if (!isBindingPattern(name)) {
25642- const nameText = getTextOfPropertyName(name);
25643- if (nameText) {
25644- const property = getPropertyOfType(parentType!, nameText); // TODO: GH#18217
25646+ if (!isBindingPattern(name) && parentType) {
25647+ const exprType = getLiteralTypeFromPropertyName(name);
25648+ if (isTypeUsableAsPropertyName(exprType)) {
25649+ const nameText = getPropertyNameFromType(exprType);
25650+ const property = getPropertyOfType(parentType, nameText);
2564525651 if (property) {
2564625652 markPropertyAsReferenced(property, /*nodeForCheckWriteOnly*/ undefined, /*isThisAccess*/ false); // A destructuring is never a write-only reference.
25647- checkPropertyAccessibility(parent, !!parent.initializer && parent.initializer.kind === SyntaxKind.SuperKeyword, parentType! , property);
25653+ checkPropertyAccessibility(parent, !!parent.initializer && parent.initializer.kind === SyntaxKind.SuperKeyword, parentType, property);
2564825654 }
2564925655 }
2565025656 }
0 commit comments