Skip to content

erase decorated abstract properties under experimentalDecorators with define semantics - #64982

Merged
Jake Bailey (jakebailey) merged 2 commits into
microsoft:mainfrom
1-DARK:fix-legacy-decorator-abstract-property-define
Nov 3, 2026
Merged

Jake Bailey (jakebailey) merged 2 commits into
microsoft:mainfrom
1-DARK:fix-legacy-decorator-abstract-property-define

Conversation

@1-DARK

Copy link
Copy Markdown
Contributor

Fixes #64980

Problem

With experimentalDecorators and define semantics (useDefineForClassFields, the default at target ES2022+), a decorated abstract property was emitted as a class field. Every instance then got an own data: undefined that shadowed whatever the decorator installed on the prototype. tsc 6.0.3 erased the field.

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

Before:

class Base { data; }
// plus the __decorate call

After:

class Base { }
// plus the __decorate call

Cause

For decorated declare/abstract properties under experimentalDecorators, typeeraser.go keeps the node so LegacyDecoratorsTransformer can emit __decorate. It rebuilds the node with VisitModifiers, which elides abstract. visitPropertyDeclaration in legacydecorators.go then finds neither NodeFlagsAmbient nor ModifierFlagsAbstract and emits a field. declare is unaffected because the node keeps NodeFlagsAmbient.

Fix

When preserving a decorated abstract property, append a declare modifier so the decorator transform erases the field. This matches Strada, which appends ModifierFlags.Ambient to the preserved node.

Tests

Added legacyDecoratorAbstractPropertyDefine (target ES2022, experimentalDecorators, useDefineForClassFields). The baseline shows no field on Base and the __decorate call intact. Also checked manually that the repro prints false from prototype.

Copilot AI balanced review requested due to automatic review settings October 27, 2026 21:03
@typescript-automation typescript-automation Bot added the For Uncommitted Bug PR for untriaged, rejected, closed or missing bug label Oct 27, 2026
@github-project-automation github-project-automation Bot moved this to Not started in PR Backlog Oct 27, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

A decorated abstract computed property with a unique-symbol key can emit an undeclared temporary because its rebuilt node lacks NodeFlagsAmbient, causing a ReferenceError during class evaluation.

1 open issue
What changed in this PR

Addresses #64980 by erasing decorated abstract fields under define semantics while preserving legacy decorator calls, restoring TypeScript 6 behavior.

Changes:

  • Adds a synthetic declare modifier to abstract properties preserved for the legacy decorator transform.
  • Adds an ES2022 regression test and baseline showing field erasure with decoration intact.
File Description
tsc/​testdata/​tests/​cases/​compiler/​legacyDecoratorAbstractPropertyDefine.ts Adds regression coverage for decorated abstract fields.
tsc/​testdata/​baselines/​reference/​compiler/​legacyDecoratorAbstractPropertyDefine.js Records erased fields and the retained __decorate call.
tsc/​internal/​transformers/​tstransforms/​typeeraser.go Marks preserved abstract properties with a synthetic declare modifier.

Review effort: Balanced

@typescript-automation typescript-automation Bot added For Backlog Bug PRs that fix a backlog bug and removed For Uncommitted Bug PR for untriaged, rejected, closed or missing bug labels Oct 30, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues were identified for the decorated abstract field emission fix.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

@jakebailey

Copy link
Copy Markdown
Member

Ideally this would be two commits, one that adds the test and "bad" baselines, then a second commit that shows the fix plus baseline update

…ors with define semantics

The baselines show the current (incorrect) output: abstract properties are emitted as class fields.
… define semantics

typeeraser keeps decorated abstract properties for the legacy decorator
transform, but VisitModifiers elides 'abstract', so the transform emitted a
field. Mark the rebuilt node ambient so it is erased like a 'declare'
property and computed keys aren't assigned to an undeclared temporary.

Fixes microsoft#64980
@1-DARK

Copy link
Copy Markdown
Contributor Author

Hi Jake Bailey (@jakebailey), done. Split into two commits: the first adds the tests with the current (bad) baselines, and the second contains the fix plus the baseline diff.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues are reported for the change intended to prevent abstract fields from shadowing decorator-defined prototype properties.

No open issues 🎉

Review effort: Balanced

@github-project-automation github-project-automation Bot moved this from Not started to Needs merge in PR Backlog Nov 3, 2026
@jakebailey
Jake Bailey (jakebailey) added this pull request to the merge queue Nov 3, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Nov 3, 2026
@jakebailey
Jake Bailey (jakebailey) added this pull request to the merge queue Nov 3, 2026
Merged via the queue into microsoft:main with commit bc4b303 Nov 3, 2026
34 checks passed
@github-project-automation github-project-automation Bot moved this from Needs merge to Done in PR Backlog Nov 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

For Backlog Bug PRs that fix a backlog bug

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

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

3 participants