From 60639ce5a80c8a651ea98ec5c30842e434a54bbc Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 22 Jan 2019 14:24:21 -0800 Subject: [PATCH] Replace most instances of getTextOfPropertyName in checker --- src/compiler/checker.ts | 92 +++++++++---------- src/compiler/types.ts | 1 + .../reference/api/tsserverlibrary.d.ts | 1 + tests/baselines/reference/api/typescript.d.ts | 1 + ...InGetTextOfComputedPropertyName.errors.txt | 36 ++++++++ ...crashInGetTextOfComputedPropertyName.types | 6 +- .../destructureComputedProperty.errors.txt | 5 +- ...redLateBoundNameHasCorrectTypes.errors.txt | 11 ++- ...ructuredLateBoundNameHasCorrectTypes.types | 2 +- ...destructuringAssignment_private.errors.txt | 14 ++- .../destructuringAssignment_private.js | 11 +++ .../destructuringAssignment_private.symbols | 21 +++++ .../destructuringAssignment_private.types | 37 ++++++++ .../destructuringAssignment_private.ts | 6 ++ 14 files changed, 188 insertions(+), 56 deletions(-) create mode 100644 tests/baselines/reference/crashInGetTextOfComputedPropertyName.errors.txt diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 48232a2e026..d38111efa1e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5280,17 +5280,18 @@ namespace ts { let objectFlags = ObjectFlags.ObjectLiteral; forEach(pattern.elements, e => { const name = e.propertyName || e.name; - if (isComputedNonLiteralName(name)) { - // do not include computed properties in the implied type - objectFlags |= ObjectFlags.ObjectLiteralPatternWithComputedProperties; - return; - } if (e.dotDotDotToken) { stringIndexInfo = createIndexInfo(anyType, /*isReadonly*/ false); return; } - const text = getTextOfPropertyName(name); + const exprType = getLiteralTypeFromPropertyName(name); + if (!isTypeUsableAsPropertyName(exprType)) { + // do not include computed properties in the implied type + objectFlags |= ObjectFlags.ObjectLiteralPatternWithComputedProperties; + return; + } + const text = getPropertyNameFromType(exprType); const flags = SymbolFlags.Property | (e.initializer ? SymbolFlags.Optional : 0); const symbol = createSymbol(flags, text); symbol.type = getTypeFromBindingElement(e, includePatternInType, reportErrors); @@ -6399,9 +6400,9 @@ namespace ts { } /** - * Indicates whether a type can be used as a late-bound name. + * Indicates whether a type can be used as a property name. */ - function isTypeUsableAsLateBoundName(type: Type): type is LiteralType | UniqueESSymbolType { + function isTypeUsableAsPropertyName(type: Type): type is StringLiteralType | NumberLiteralType | UniqueESSymbolType { return !!(type.flags & TypeFlags.StringOrNumberLiteralOrUnique); } @@ -6416,7 +6417,7 @@ namespace ts { function isLateBindableName(node: DeclarationName): node is LateBoundName { return isComputedPropertyName(node) && isEntityNameExpression(node.expression) - && isTypeUsableAsLateBoundName(checkComputedPropertyName(node)); + && isTypeUsableAsPropertyName(checkComputedPropertyName(node)); } function isLateBoundName(name: __String): boolean { @@ -6448,21 +6449,14 @@ namespace ts { } /** - * Gets the late-bound name for a computed property name. + * Gets the symbolic name for a member from its type. */ - function getLateBoundName(node: LateBoundName) { - return getLateBoundNameFromType(checkComputedPropertyName(node)); - } - - /** - * Gets the symbolic name for a late-bound member from its type. - */ - function getLateBoundNameFromType(type: LiteralType | UniqueESSymbolType): __String { + function getPropertyNameFromType(type: StringLiteralType | NumberLiteralType | UniqueESSymbolType): __String { if (type.flags & TypeFlags.UniqueESSymbol) { - return `__@${type.symbol.escapedName}@${getSymbolId(type.symbol)}` as __String; + return (type).escapedName; } if (type.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral)) { - return escapeLeadingUnderscores("" + (type).value); + return escapeLeadingUnderscores("" + (type).value); } return Debug.fail(); } @@ -6525,8 +6519,8 @@ namespace ts { // fall back to the early-bound name of this member. links.resolvedSymbol = decl.symbol; const type = checkComputedPropertyName(decl.name); - if (isTypeUsableAsLateBoundName(type)) { - const memberName = getLateBoundNameFromType(type); + if (isTypeUsableAsPropertyName(type)) { + const memberName = getPropertyNameFromType(type); const symbolFlags = decl.symbol.flags; // Get or add a late-bound symbol for the member. This allows us to merge late-bound accessor declarations. @@ -7175,8 +7169,8 @@ namespace ts { const propType = instantiateType(templateType, templateMapper); // If the current iteration type constituent is a string literal type, create a property. // Otherwise, for type string create a string index signature. - if (t.flags & TypeFlags.StringOrNumberLiteralOrUnique) { - const propName = getLateBoundNameFromType(t as LiteralType); + if (isTypeUsableAsPropertyName(t)) { + const propName = getPropertyNameFromType(t); const modifiersProp = getPropertyOfType(modifiersType, propName); const isOptional = !!(templateModifiers & MappedTypeModifiers.IncludeOptional || !(templateModifiers & MappedTypeModifiers.ExcludeOptional) && modifiersProp && modifiersProp.flags & SymbolFlags.Optional); @@ -7361,7 +7355,8 @@ namespace ts { function isTypeInvalidDueToUnionDiscriminant(contextualType: Type, obj: ObjectLiteralExpression | JsxAttributes): boolean { const list = obj.properties as NodeArray; return list.some(property => { - const name = property.name && !isComputedNonLiteralName(property.name) ? getTextOfPropertyName(property.name) : undefined; + const nameType = property.name && getLiteralTypeFromPropertyName(property.name); + const name = nameType && isTypeUsableAsPropertyName(nameType) ? getPropertyNameFromType(nameType) : undefined; const expected = name === undefined ? undefined : getTypeOfPropertyOfType(contextualType, name); return !!expected && isLiteralType(expected) && !isTypeIdenticalTo(getTypeOfNode(property), expected); }); @@ -9724,8 +9719,8 @@ namespace ts { function getPropertyTypeForIndexType(objectType: Type, indexType: Type, accessNode: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression | undefined, cacheSymbol: boolean, missingType: Type) { const accessExpression = accessNode && accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode : undefined; - const propName = isTypeUsableAsLateBoundName(indexType) ? - getLateBoundNameFromType(indexType) : + const propName = isTypeUsableAsPropertyName(indexType) ? + getPropertyNameFromType(indexType) : accessExpression && checkThatExpressionIsProperSymbolReference(accessExpression.argumentExpression, indexType, /*reportError*/ false) ? getPropertyNameForKnownSymbolName(idText((accessExpression.argumentExpression).name)) : accessNode && isPropertyName(accessNode) ? @@ -10415,6 +10410,7 @@ namespace ts { function createUniqueESSymbolType(symbol: Symbol) { const type = createType(TypeFlags.UniqueESSymbol); type.symbol = symbol; + type.escapedName = `__@${type.symbol.escapedName}@${getSymbolId(type.symbol)}` as __String; return type; } @@ -11302,7 +11298,7 @@ namespace ts { } if (resultObj.error) { const reportedDiag = resultObj.error; - const propertyName = isTypeUsableAsLateBoundName(nameType) ? getLateBoundNameFromType(nameType) : undefined; + const propertyName = isTypeUsableAsPropertyName(nameType) ? getPropertyNameFromType(nameType) : undefined; const targetProp = propertyName !== undefined ? getPropertyOfType(target, propertyName) : undefined; let issuedElaboration = false; @@ -15066,10 +15062,9 @@ namespace ts { } function getTypeOfDestructuredProperty(type: Type, name: PropertyName) { - const text = !isComputedNonLiteralName(name) ? getTextOfPropertyName(name) : - isLateBindableName(name) ? getLateBoundName(name) : - undefined; - if (text === undefined) return errorType; + const nameType = getLiteralTypeFromPropertyName(name); + if (!isTypeUsableAsPropertyName(nameType)) return errorType; + const text = getPropertyNameFromType(nameType); return getConstraintForLocation(getTypeOfPropertyOfType(type, text), name) || isNumericLiteralName(text) && getIndexTypeOfType(type, IndexKind.Number) || getIndexTypeOfType(type, IndexKind.String) || @@ -17202,8 +17197,11 @@ namespace ts { const name = declaration.propertyName || declaration.name; const parentType = getContextualTypeForVariableLikeDeclaration(parentDeclaration); if (parentType && !isBindingPattern(name) && !isComputedNonLiteralName(name)) { - const text = getTextOfPropertyName(name); - return getTypeOfPropertyOfType(parentType, text); + const nameType = getLiteralTypeFromPropertyName(name); + if (isTypeUsableAsPropertyName(nameType)) { + const text = getPropertyNameFromType(nameType); + return getTypeOfPropertyOfType(parentType, text); + } } } @@ -18146,10 +18144,9 @@ namespace ts { } } typeFlags |= type.flags; - const nameType = computedNameType && computedNameType.flags & TypeFlags.StringOrNumberLiteralOrUnique ? - computedNameType : undefined; + const nameType = computedNameType && isTypeUsableAsPropertyName(computedNameType) ? computedNameType : undefined; const prop = nameType ? - createSymbol(SymbolFlags.Property | member.flags, getLateBoundNameFromType(nameType), CheckFlags.Late) : + createSymbol(SymbolFlags.Property | member.flags, getPropertyNameFromType(nameType), CheckFlags.Late) : createSymbol(SymbolFlags.Property | member.flags, member.escapedName); if (nameType) { prop.nameType = nameType; @@ -22209,15 +22206,15 @@ namespace ts { function checkObjectLiteralDestructuringPropertyAssignment(objectLiteralType: Type, property: ObjectLiteralElementLike, allProperties?: NodeArray, rightIsThis = false) { if (property.kind === SyntaxKind.PropertyAssignment || property.kind === SyntaxKind.ShorthandPropertyAssignment) { const name = property.name; - if (!isComputedNonLiteralName(name)) { - const text = getTextOfPropertyName(name); + const exprType = getLiteralTypeFromPropertyName(name); + if (isTypeUsableAsPropertyName(exprType)) { + const text = getPropertyNameFromType(exprType); const prop = getPropertyOfType(objectLiteralType, text); if (prop) { markPropertyAsReferenced(prop, property, rightIsThis); checkPropertyAccessibility(property, /*isSuper*/ false, objectLiteralType, prop); } } - const exprType = getLiteralTypeFromPropertyName(name); const elementType = getIndexedAccessType(objectLiteralType, exprType, name); const type = getFlowTypeOfDestructuring(property, elementType); return checkDestructuringAssignment(property.kind === SyntaxKind.ShorthandPropertyAssignment ? property : property.initializer, type); @@ -25532,12 +25529,15 @@ namespace ts { const parent = node.parent.parent; const parentType = getTypeForBindingElementParent(parent); const name = node.propertyName || node.name; - if (!isBindingPattern(name) && !isComputedNonLiteralName(name)) { - const nameText = getTextOfPropertyName(name); - const property = getPropertyOfType(parentType!, nameText); // TODO: GH#18217 - if (property) { - markPropertyAsReferenced(property, /*nodeForCheckWriteOnly*/ undefined, /*isThisAccess*/ false); // A destructuring is never a write-only reference. - checkPropertyAccessibility(parent, !!parent.initializer && parent.initializer.kind === SyntaxKind.SuperKeyword, parentType!, property); + if (!isBindingPattern(name) && parentType) { + const exprType = getLiteralTypeFromPropertyName(name); + if (isTypeUsableAsPropertyName(exprType)) { + const nameText = getPropertyNameFromType(exprType); + const property = getPropertyOfType(parentType, nameText); + if (property) { + markPropertyAsReferenced(property, /*nodeForCheckWriteOnly*/ undefined, /*isThisAccess*/ false); // A destructuring is never a write-only reference. + checkPropertyAccessibility(parent, !!parent.initializer && parent.initializer.kind === SyntaxKind.SuperKeyword, parentType!, property); + } } } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 125c3297863..8b4be87d925 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3952,6 +3952,7 @@ namespace ts { // Unique symbol types (TypeFlags.UniqueESSymbol) export interface UniqueESSymbolType extends Type { symbol: Symbol; + escapedName: __String; } export interface StringLiteralType extends LiteralType { diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 91f492ddd1d..152ffe33a10 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2214,6 +2214,7 @@ declare namespace ts { } interface UniqueESSymbolType extends Type { symbol: Symbol; + escapedName: __String; } interface StringLiteralType extends LiteralType { value: string; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 0e693f698f2..077bd9646d0 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2214,6 +2214,7 @@ declare namespace ts { } interface UniqueESSymbolType extends Type { symbol: Symbol; + escapedName: __String; } interface StringLiteralType extends LiteralType { value: string; diff --git a/tests/baselines/reference/crashInGetTextOfComputedPropertyName.errors.txt b/tests/baselines/reference/crashInGetTextOfComputedPropertyName.errors.txt new file mode 100644 index 00000000000..4997400674c --- /dev/null +++ b/tests/baselines/reference/crashInGetTextOfComputedPropertyName.errors.txt @@ -0,0 +1,36 @@ +tests/cases/compiler/crashInGetTextOfComputedPropertyName.ts(23,24): error TS2525: Initializer provides no value for this binding element and the binding element has no default value. + + +==== tests/cases/compiler/crashInGetTextOfComputedPropertyName.ts (1 errors) ==== + // https://github.com/Microsoft/TypeScript/issues/29006 + export interface A { type: 'a' } + export interface B { type: 'b' } + export type AB = A | B + + const itemId = 'some-id' + + // --- test on first level --- + const items: { [id: string]: AB } = {} + const { [itemId]: itemOk1 } = items + typeof itemOk1 // pass + + // --- test on second level --- + interface ObjWithItems { + items: {[s: string]: AB} + } + const objWithItems: ObjWithItems = { items: {}} + + const itemOk2 = objWithItems.items[itemId] + typeof itemOk2 // pass + + const { + items: { [itemId]: itemWithTSError } = {} /*happens when default value is provided*/ + ~~~~~~~~~~~~~~~ +!!! error TS2525: Initializer provides no value for this binding element and the binding element has no default value. + } = objWithItems + + // in order to re-produce the error, uncomment next line: + typeof itemWithTSError // :( + + // will result in: + // Error from compilation: TypeError: Cannot read property 'charCodeAt' of undefined TypeError: Cannot read property 'charCodeAt' of undefined \ No newline at end of file diff --git a/tests/baselines/reference/crashInGetTextOfComputedPropertyName.types b/tests/baselines/reference/crashInGetTextOfComputedPropertyName.types index 7d9ce4aa34b..4eeb487bdfb 100644 --- a/tests/baselines/reference/crashInGetTextOfComputedPropertyName.types +++ b/tests/baselines/reference/crashInGetTextOfComputedPropertyName.types @@ -56,8 +56,8 @@ const { items: { [itemId]: itemWithTSError } = {} /*happens when default value is provided*/ >items : any >itemId : "some-id" ->itemWithTSError : AB ->{} : {} +>itemWithTSError : any +>{} : { some-id: any; } } = objWithItems >objWithItems : ObjWithItems @@ -65,7 +65,7 @@ const { // in order to re-produce the error, uncomment next line: typeof itemWithTSError // :( >typeof itemWithTSError : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" ->itemWithTSError : AB +>itemWithTSError : any // will result in: // Error from compilation: TypeError: Cannot read property 'charCodeAt' of undefined TypeError: Cannot read property 'charCodeAt' of undefined diff --git a/tests/baselines/reference/destructureComputedProperty.errors.txt b/tests/baselines/reference/destructureComputedProperty.errors.txt index 5b39820988a..ad6e8042f87 100644 --- a/tests/baselines/reference/destructureComputedProperty.errors.txt +++ b/tests/baselines/reference/destructureComputedProperty.errors.txt @@ -1,9 +1,10 @@ tests/cases/compiler/destructureComputedProperty.ts(7,7): error TS2341: Property 'p' is private and only accessible within class 'C'. tests/cases/compiler/destructureComputedProperty.ts(8,7): error TS2341: Property 'p' is private and only accessible within class 'C'. +tests/cases/compiler/destructureComputedProperty.ts(9,7): error TS2341: Property 'p' is private and only accessible within class 'C'. tests/cases/compiler/destructureComputedProperty.ts(10,7): error TS2341: Property 'p' is private and only accessible within class 'C'. -==== tests/cases/compiler/destructureComputedProperty.ts (3 errors) ==== +==== tests/cases/compiler/destructureComputedProperty.ts (4 errors) ==== declare const ab: { n: number } | { n: string }; const nameN = "n"; const { [nameN]: n } = ab; @@ -17,6 +18,8 @@ tests/cases/compiler/destructureComputedProperty.ts(10,7): error TS2341: Propert ~~~~~~~~~~~~~ !!! error TS2341: Property 'p' is private and only accessible within class 'C'. const { [nameP]: p2 } = new C(); + ~~~~~~~~~~~~~~~ +!!! error TS2341: Property 'p' is private and only accessible within class 'C'. const { p: p3 } = new C(); ~~~~~~~~~ !!! error TS2341: Property 'p' is private and only accessible within class 'C'. diff --git a/tests/baselines/reference/destructuredLateBoundNameHasCorrectTypes.errors.txt b/tests/baselines/reference/destructuredLateBoundNameHasCorrectTypes.errors.txt index 100ce2d9a08..6d3d288af74 100644 --- a/tests/baselines/reference/destructuredLateBoundNameHasCorrectTypes.errors.txt +++ b/tests/baselines/reference/destructuredLateBoundNameHasCorrectTypes.errors.txt @@ -1,7 +1,8 @@ -tests/cases/compiler/destructuredLateBoundNameHasCorrectTypes.ts(11,8): error TS2339: Property 'prop2' does not exist on type '{ prop: string; }'. +tests/cases/compiler/destructuredLateBoundNameHasCorrectTypes.ts(11,21): error TS2525: Initializer provides no value for this binding element and the binding element has no default value. +tests/cases/compiler/destructuredLateBoundNameHasCorrectTypes.ts(11,37): error TS2353: Object literal may only specify known properties, and 'prop' does not exist in type '{ prop2: any; }'. -==== tests/cases/compiler/destructuredLateBoundNameHasCorrectTypes.ts (1 errors) ==== +==== tests/cases/compiler/destructuredLateBoundNameHasCorrectTypes.ts (2 errors) ==== let { [Symbol.iterator]: destructured } = []; void destructured; @@ -13,6 +14,8 @@ tests/cases/compiler/destructuredLateBoundNameHasCorrectTypes.ts(11,8): error TS const notPresent = "prop2"; let { [notPresent]: computed2 } = { prop: "b" }; - ~~~~~~~~~~ -!!! error TS2339: Property 'prop2' does not exist on type '{ prop: string; }'. + ~~~~~~~~~ +!!! error TS2525: Initializer provides no value for this binding element and the binding element has no default value. + ~~~~ +!!! error TS2353: Object literal may only specify known properties, and 'prop' does not exist in type '{ prop2: any; }'. \ No newline at end of file diff --git a/tests/baselines/reference/destructuredLateBoundNameHasCorrectTypes.types b/tests/baselines/reference/destructuredLateBoundNameHasCorrectTypes.types index 8d24b45e0ec..8342017958a 100644 --- a/tests/baselines/reference/destructuredLateBoundNameHasCorrectTypes.types +++ b/tests/baselines/reference/destructuredLateBoundNameHasCorrectTypes.types @@ -32,7 +32,7 @@ const notPresent = "prop2"; let { [notPresent]: computed2 } = { prop: "b" }; >notPresent : "prop2" >computed2 : any ->{ prop: "b" } : { prop: string; } +>{ prop: "b" } : { prop: string; prop2: any; } >prop : string >"b" : "b" diff --git a/tests/baselines/reference/destructuringAssignment_private.errors.txt b/tests/baselines/reference/destructuringAssignment_private.errors.txt index f17f1610d0a..2afd1606ebb 100644 --- a/tests/baselines/reference/destructuringAssignment_private.errors.txt +++ b/tests/baselines/reference/destructuringAssignment_private.errors.txt @@ -1,8 +1,10 @@ tests/cases/compiler/destructuringAssignment_private.ts(6,10): error TS2341: Property 'x' is private and only accessible within class 'C'. tests/cases/compiler/destructuringAssignment_private.ts(7,4): error TS2341: Property 'o' is private and only accessible within class 'C'. +tests/cases/compiler/destructuringAssignment_private.ts(10,10): error TS2341: Property 'x' is private and only accessible within class 'C'. +tests/cases/compiler/destructuringAssignment_private.ts(13,4): error TS2341: Property 'o' is private and only accessible within class 'C'. -==== tests/cases/compiler/destructuringAssignment_private.ts (2 errors) ==== +==== tests/cases/compiler/destructuringAssignment_private.ts (4 errors) ==== class C { private x = 0; private o = [{ a: 1 }]; @@ -14,4 +16,14 @@ tests/cases/compiler/destructuringAssignment_private.ts(7,4): error TS2341: Prop ({ o: [{ a: x }]} = new C()); ~ !!! error TS2341: Property 'o' is private and only accessible within class 'C'. + + const nameX = "x"; + ([{ a: { [nameX]: x } }] = [{ a: new C() }]); + ~~~~~~~ +!!! error TS2341: Property 'x' is private and only accessible within class 'C'. + + const nameO = "o"; + ({ [nameO]: [{ a: x }]} = new C()); + ~~~~~~~ +!!! error TS2341: Property 'o' is private and only accessible within class 'C'. \ No newline at end of file diff --git a/tests/baselines/reference/destructuringAssignment_private.js b/tests/baselines/reference/destructuringAssignment_private.js index 6201ad3578e..b8f4130761b 100644 --- a/tests/baselines/reference/destructuringAssignment_private.js +++ b/tests/baselines/reference/destructuringAssignment_private.js @@ -6,9 +6,16 @@ class C { let x: number; ([{ a: { x } }] = [{ a: new C() }]); ({ o: [{ a: x }]} = new C()); + +const nameX = "x"; +([{ a: { [nameX]: x } }] = [{ a: new C() }]); + +const nameO = "o"; +({ [nameO]: [{ a: x }]} = new C()); //// [destructuringAssignment_private.js] +var _a, _b; var C = /** @class */ (function () { function C() { this.x = 0; @@ -19,3 +26,7 @@ var C = /** @class */ (function () { var x; (x = [{ a: new C() }][0].a.x); (x = new C().o[0].a); +var nameX = "x"; +(_a = nameX, x = [{ a: new C() }][0].a[_a]); +var nameO = "o"; +(_b = nameO, x = new C()[_b][0].a); diff --git a/tests/baselines/reference/destructuringAssignment_private.symbols b/tests/baselines/reference/destructuringAssignment_private.symbols index b3a7abce5bf..be325bda639 100644 --- a/tests/baselines/reference/destructuringAssignment_private.symbols +++ b/tests/baselines/reference/destructuringAssignment_private.symbols @@ -24,3 +24,24 @@ let x: number; >x : Symbol(x, Decl(destructuringAssignment_private.ts, 4, 3)) >C : Symbol(C, Decl(destructuringAssignment_private.ts, 0, 0)) +const nameX = "x"; +>nameX : Symbol(nameX, Decl(destructuringAssignment_private.ts, 8, 5)) + +([{ a: { [nameX]: x } }] = [{ a: new C() }]); +>a : Symbol(a, Decl(destructuringAssignment_private.ts, 9, 3)) +>[nameX] : Symbol([nameX], Decl(destructuringAssignment_private.ts, 9, 8)) +>nameX : Symbol(nameX, Decl(destructuringAssignment_private.ts, 8, 5)) +>x : Symbol(x, Decl(destructuringAssignment_private.ts, 4, 3)) +>a : Symbol(a, Decl(destructuringAssignment_private.ts, 9, 29)) +>C : Symbol(C, Decl(destructuringAssignment_private.ts, 0, 0)) + +const nameO = "o"; +>nameO : Symbol(nameO, Decl(destructuringAssignment_private.ts, 11, 5)) + +({ [nameO]: [{ a: x }]} = new C()); +>[nameO] : Symbol([nameO], Decl(destructuringAssignment_private.ts, 12, 2)) +>nameO : Symbol(nameO, Decl(destructuringAssignment_private.ts, 11, 5)) +>a : Symbol(a, Decl(destructuringAssignment_private.ts, 12, 14)) +>x : Symbol(x, Decl(destructuringAssignment_private.ts, 4, 3)) +>C : Symbol(C, Decl(destructuringAssignment_private.ts, 0, 0)) + diff --git a/tests/baselines/reference/destructuringAssignment_private.types b/tests/baselines/reference/destructuringAssignment_private.types index f126a973f1d..0615429cef5 100644 --- a/tests/baselines/reference/destructuringAssignment_private.types +++ b/tests/baselines/reference/destructuringAssignment_private.types @@ -42,3 +42,40 @@ let x: number; >new C() : C >C : typeof C +const nameX = "x"; +>nameX : "x" +>"x" : "x" + +([{ a: { [nameX]: x } }] = [{ a: new C() }]); +>([{ a: { [nameX]: x } }] = [{ a: new C() }]) : [{ a: C; }] +>[{ a: { [nameX]: x } }] = [{ a: new C() }] : [{ a: C; }] +>[{ a: { [nameX]: x } }] : [{ a: { [nameX]: number; }; }] +>{ a: { [nameX]: x } } : { a: { [nameX]: number; }; } +>a : { [nameX]: number; } +>{ [nameX]: x } : { [nameX]: number; } +>[nameX] : number +>nameX : "x" +>x : number +>[{ a: new C() }] : [{ a: C; }] +>{ a: new C() } : { a: C; } +>a : C +>new C() : C +>C : typeof C + +const nameO = "o"; +>nameO : "o" +>"o" : "o" + +({ [nameO]: [{ a: x }]} = new C()); +>({ [nameO]: [{ a: x }]} = new C()) : C +>{ [nameO]: [{ a: x }]} = new C() : C +>{ [nameO]: [{ a: x }]} : { [nameO]: [{ a: number; }]; } +>[nameO] : [{ a: number; }] +>nameO : "o" +>[{ a: x }] : [{ a: number; }] +>{ a: x } : { a: number; } +>a : number +>x : number +>new C() : C +>C : typeof C + diff --git a/tests/cases/compiler/destructuringAssignment_private.ts b/tests/cases/compiler/destructuringAssignment_private.ts index bdc057851ae..62f4101838d 100644 --- a/tests/cases/compiler/destructuringAssignment_private.ts +++ b/tests/cases/compiler/destructuringAssignment_private.ts @@ -5,3 +5,9 @@ class C { let x: number; ([{ a: { x } }] = [{ a: new C() }]); ({ o: [{ a: x }]} = new C()); + +const nameX = "x"; +([{ a: { [nameX]: x } }] = [{ a: new C() }]); + +const nameO = "o"; +({ [nameO]: [{ a: x }]} = new C());