`--experimentalDecorators`: decorated `abstract` property is emitted as a class field (regression in 7.0)

Offen
#64,980 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Maintainer antworten meist innerhalb von 1 Tag

@1-DARK arbeitet bereits daran.

Seit 27.10.2026.

  • #64982 von @1-DARK — offen

Bewertung

Schwierigkeit
4/5
Geschätzter Aufwand
1-2 Tage
Anfängerfreundlichkeit
35/100
Issue-Typ
Bug
Klarheit
Klar beschrieben
Aktivitätsstatus
Veraltet
Tech-Stack
typescript
Bereich
compilers

Rechercherichtung

Start by reading typeeraser.go around the decorated declare and abstract property handling, then follow visitPropertyDeclaration in legacydecorators.go to see why the preserved node emits a field. Compare with the visitPropertyDeclaration handling in ts.ts described in the issue. Done means the abstract property is erased while its legacy decorator call remains, matching the expected output; an open pull request is already linked.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Beschreibung

Bug
🔎 Search Terms

experimentalDecorators, abstract property, decorator, class field, useDefineForClassFields, typeeraser, legacy decorators

🕗 Version & Regression Information
  • Regression from tsc 6.0.3, which erases the field.
  • Reproduces in 7.0.2, 7.1.0-beta and 7.1.0-dev.20261026.1.
💻 Code
function dec(target: object, key: string) {
  Object.defineProperty(target, key, { get: () => 'from prototype', configurable: true });
}

abstract class Base {
  @dec abstract data: string;
}

class Sub extends Base {
  declare data: string;
}

const s = new Sub();
console.log(Object.hasOwn(s, 'data'), s.data);
{ "compilerOptions": { "target": "es2022", "experimentalDecorators": true } }
🙁 Actual behavior

Base gets a data; field, so every instance has an own data: undefined that shadows whatever the decorator put on the prototype. Prints true undefined.

class Base {
    data;
}
__decorate([
    dec
], Base.prototype, "data", void 0);
🙂 Expected behavior

Same as tsc 6.0.3: the field is erased and only the __decorate call remains. Prints false from prototype.

class Base {
}
__decorate([
    dec
], Base.prototype, "data", void 0);
Additional information about the issue

The field appears only when all three hold: experimentalDecorators, a decorator on the abstract property, and define semantics (useDefineForClassFields, the default at target ES2022 and later). emitDecoratorMetadata makes no difference. An undecorated abstract property and a decorated declare property are both still erased.

The likely cause is in typeeraser.go. For a decorated declare/abstract property under experimentalDecorators, it keeps the node so that LegacyDecoratorsTransformer can emit the __decorate call. But it rebuilds the node with VisitModifiers, which elides AbstractKeyword. visitPropertyDeclaration in legacydecorators.go then finds neither NodeFlagsAmbient nor ModifierFlagsAbstract and emits a field. declare escapes this because the node keeps NodeFlagsAmbient. Strada's visitPropertyDeclaration in ts.ts handles the same case by appending a declare modifier to the preserved node (concatenate(modifiers, factory.createModifiersFromModifierFlags(ModifierFlags.Ambient))).

We hit this in TypeORM entities: an abstract base declares a decorated abstract column, each subclass redeclares it with declare, and every entity instance gains an own data: undefined it doesn't have under tsc 6.

Vorherrschende Sprache
Go
Sterne
112k
Forks
15.4k
Ø Merge
3 T. 1 Std.
Gemergte PRs (30 T.)
136

Entwicklungsumgebung

In Codespaces öffnen

Startet den Dev-Container des Projekts im Browser, mit Ihrem eigenen GitHub-Konto.

Erste Schritte

  1. Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
  3. Forken Sie das Repository und arbeiten Sie in einem Branch.
  4. Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.

Mehr aus microsoft/TypeScript

Alle Issues in microsoft/TypeScript

Ähnliche Issues

Weitere Issues zu Go

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.