Skip to content

Invalid emit for property decorators on computed property names in classes #17028

@Chacha-26

Description

@Chacha-26

TypeScript Version: 2.4.0 / nightly (2.5.0-dev.20170707)

N.B.: The syntax for using x[0] as a decorator is @(x[0]) with parentheses. @x[0] without parentheses is the decorator x applied to the property 0.

Code (Playground link):

function x(o: object, k: PropertyKey) { }
class A {
    @x ["property"]: any;
    @x [Symbol.toStringTag]: any;
}

Expected behavior:

The standard emit for classes, followed by:

__decorate([
    x
], A.prototype, "property", void 0);
__decorate([
    x
], A.prototype, Symbol.toStringTag, void 0);

Actual behavior:

The standard emit for classes, followed by:

__decorate([
    x
], A.prototype, _a, void 0);
__decorate([
    x
], A.prototype, _b, void 0);

This causes a reference error since _a and _b are never declared.
Note that this doesn't affect string property names without the square brackets (e.g. @x "property": any;), but this is still an issue when Symbols as property names.


In addition, the temporary variables produced for methods, properties, and properties with values are all conflicting (Playground link):

function x(o: object, k: PropertyKey) { }
class A {
    @x [Symbol.unscopables] = {};
    @x [Symbol.match]() { }
    @x [Symbol.toStringTag]: string;
}

produces

function x(o, k) { }
class A {
    constructor() {
        this[_a = Symbol.unscopables] = {};
        var _a;
    }
    [_a = Symbol.match]() { }
}
__decorate([
    x
], A.prototype, _a, void 0);
__decorate([
    x
], A.prototype, _a, null);
__decorate([
    x
], A.prototype, _a, void 0);
var _a;

In this case there are three distinct _a variables used in the same scope:

  1. For Symbol.unscopables: Declared on line 5, but used out of scope.
  2. For Symbol.match: Declared on line 18 and used in scope. This works as expected.
  3. For Symbol.toStringTag: Never declared.

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptFixedA PR has been merged for this issue

Type

No type
No fields configured for issues without a type.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions