From 330b83d7d5472a083153d9a3acef67018507c7f3 Mon Sep 17 00:00:00 2001 From: Liam Date: Mon, 29 Jun 2026 12:22:38 +0100 Subject: [PATCH] Allow decorators to be used with `declare` on class fields (#19492) Co-authored-by: fisker --- changelog_unreleased/typescript/19492.md | 23 ++++++++++ src/language-js/parse/babel.js | 7 +++ tests/format/typescript/comments/16065-2.ts | 8 ++++ .../__snapshots__/format.test.js.snap | 16 +++++++ .../__snapshots__/format.test.js.snap | 43 +++++++++++++++++++ .../decorators/decorators-comments.ts | 6 +++ tests/format/typescript/decorators/ember.ts | 10 +++++ 7 files changed, 113 insertions(+) create mode 100644 changelog_unreleased/typescript/19492.md create mode 100644 tests/format/typescript/decorators/ember.ts diff --git a/changelog_unreleased/typescript/19492.md b/changelog_unreleased/typescript/19492.md new file mode 100644 index 000000000..72ca50d6d --- /dev/null +++ b/changelog_unreleased/typescript/19492.md @@ -0,0 +1,23 @@ +#### Allow decorators to be used with declare on class fields (#19492 by @evoactivity) + +Extensively used within the Ember ecosystem, decorators with `declare` on class fields will ignore the babel parser error and allow Prettier to format the code without breaking it. + + +```ts +// Input +export default class ProjectStatusComponent extends Component { + @service declare server: ServerService; +} + +// Prettier stable +// SyntaxError: Decorators can't be used with a declare field. (2:3) +// 1 | export default class ProjectStatusComponent extends Component { +//> 2 | @service declare server: ServerService; +// | ^ +// 3 | } + +// Prettier main +export default class ProjectStatusComponent extends Component { + @service declare server: ServerService; +} +``` diff --git a/src/language-js/parse/babel.js b/src/language-js/parse/babel.js index a8b7f959a..fc8c04124 100644 --- a/src/language-js/parse/babel.js +++ b/src/language-js/parse/babel.js @@ -222,6 +222,13 @@ const allowedReasonCodesArray = [ ``` */ "DeclarationMissingInitializer", + + /* + Allow decorators to be used with declare fields + https://github.com/prettier/prettier/issues/19491 + https://github.com/babel/babel/pull/17949 + */ + "DecoratorAbstractMethod", ]; const allowedReasonCodes = new Set(allowedReasonCodesArray); diff --git a/tests/format/typescript/comments/16065-2.ts b/tests/format/typescript/comments/16065-2.ts index 9917a4275..f63e84107 100644 --- a/tests/format/typescript/comments/16065-2.ts +++ b/tests/format/typescript/comments/16065-2.ts @@ -3,6 +3,14 @@ class Foo { @decorator readonly /* comment */ propertyDefinition; + // TSAbstractPropertyDefinition + @decorator + abstract /* comment */ abstractPropertyDefinition; + + // TSAbstractMethodDefinition + @decorator + abstract /* comment */ abstractMethodDefinition; + // MethodDefinition @decorator private /* comment */ methodDefinition() {} diff --git a/tests/format/typescript/comments/__snapshots__/format.test.js.snap b/tests/format/typescript/comments/__snapshots__/format.test.js.snap index 41d73e3b7..9f38d3caa 100644 --- a/tests/format/typescript/comments/__snapshots__/format.test.js.snap +++ b/tests/format/typescript/comments/__snapshots__/format.test.js.snap @@ -260,6 +260,14 @@ class Foo { @decorator readonly /* comment */ propertyDefinition; + // TSAbstractPropertyDefinition + @decorator + abstract /* comment */ abstractPropertyDefinition; + + // TSAbstractMethodDefinition + @decorator + abstract /* comment */ abstractMethodDefinition; + // MethodDefinition @decorator private /* comment */ methodDefinition() {} @@ -281,6 +289,14 @@ class Foo { @decorator readonly /* comment */ propertyDefinition; + // TSAbstractPropertyDefinition + @decorator + abstract /* comment */ abstractPropertyDefinition; + + // TSAbstractMethodDefinition + @decorator + abstract /* comment */ abstractMethodDefinition; + // MethodDefinition @decorator private /* comment */ methodDefinition() {} diff --git a/tests/format/typescript/decorators/__snapshots__/format.test.js.snap b/tests/format/typescript/decorators/__snapshots__/format.test.js.snap index acb96cb21..32bf67b7b 100644 --- a/tests/format/typescript/decorators/__snapshots__/format.test.js.snap +++ b/tests/format/typescript/decorators/__snapshots__/format.test.js.snap @@ -292,6 +292,12 @@ class Something { readonly property: Array } +class Something2 { + @foo() + // comment + abstract property: Array +} + =====================================output===================================== class Foo1 { @foo @@ -323,6 +329,43 @@ class Something { readonly property: Array; } +class Something2 { + @foo() + // comment + abstract property: Array; +} + +================================================================================ +`; + +exports[`ember.ts format 1`] = ` +====================================options===================================== +parsers: ["typescript"] + printWidth: 80 (default) | +=====================================input====================================== +/* +https://github.com/prettier/prettier/issues/19491 + +decorators with declare is used extensively in Ember ecosystem, +and we want to make sure that Prettier doesn't break them. +*/ + +export default class ProjectStatusComponent extends Component { + @service declare server: ServerService; +} + +=====================================output===================================== +/* +https://github.com/prettier/prettier/issues/19491 + +decorators with declare is used extensively in Ember ecosystem, +and we want to make sure that Prettier doesn't break them. +*/ + +export default class ProjectStatusComponent extends Component { + @service declare server: ServerService; +} + ================================================================================ `; diff --git a/tests/format/typescript/decorators/decorators-comments.ts b/tests/format/typescript/decorators/decorators-comments.ts index b3158563d..2f3c378a9 100644 --- a/tests/format/typescript/decorators/decorators-comments.ts +++ b/tests/format/typescript/decorators/decorators-comments.ts @@ -28,3 +28,9 @@ class Something { // comment readonly property: Array } + +class Something2 { + @foo() + // comment + abstract property: Array +} diff --git a/tests/format/typescript/decorators/ember.ts b/tests/format/typescript/decorators/ember.ts new file mode 100644 index 000000000..7b94dc883 --- /dev/null +++ b/tests/format/typescript/decorators/ember.ts @@ -0,0 +1,10 @@ +/* +https://github.com/prettier/prettier/issues/19491 + +decorators with declare is used extensively in Ember ecosystem, +and we want to make sure that Prettier doesn't break them. +*/ + +export default class ProjectStatusComponent extends Component { + @service declare server: ServerService; +}