babel: [Bug]: failed to transform Class fields with `declare` modifier in TypeScript

πŸ’»

  • Would you like to work on a fix?

How are you using Babel?

Other (Next.js, Gatsby, vue-cli, …)

Input code

const decorator = (Class: new () => any, {}: ClassDecoratorContext) =>
    class SubClass extends Class {
        accessor field: Record<string, any> = {};
    }

@decorator
export class Example {
    declare field: Record<string, any>;
}

Configuration file name

No response

Configuration

module.exports = {
  presets: [
    // https://babeljs.io/docs/babel-preset-typescript
    [
      '@babel/preset-typescript',
      {
        allowDeclareFields: true,
        allowNamespaces: true,
        allExtensions: true,
        isTSX: true,
      },
    ],
    // https://babeljs.io/docs/babel-preset-react
    [
      '@babel/preset-react',
      {
        runtime: 'automatic',
        development: process.env.BABEL_ENV === 'development',
      },
    ],
  ],
  // https://babeljs.io/docs/babel-plugin-proposal-decorators#note-compatibility-with-babelplugin-transform-class-properties
  plugins: [['@babel/plugin-proposal-decorators', { version: '2023-05' }]],
};

Current and expected behavior

Expect this error to be fixed:

SyntaxError: Fields with the 'declare' modifier cannot be initialized here, but only in the constructor 

Environment

  System:
    OS: Windows 10 10.0.19045
  Binaries:
    Node: 18.17.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.19 - C:\Program Files (x86)\Yarn\bin\yarn.CMD
    npm: 10.1.0 - C:\Program Files\nodejs\npm.CMD
    pnpm: 8.15.1 - C:\Program Files\nodejs\pnpm.CMD
  npmPackages:
    @babel/plugin-proposal-decorators: ^7.23.9 => 7.23.9
    @babel/preset-react: ^7.23.3 => 7.23.3
    @babel/preset-typescript: ^7.23.3 => 7.23.3
    eslint: ^8.56.0 => 8.56.0
    webpack: ^5.90.1 => 5.90.1

Possible solution

The throw logic needs node.value existed, but my code has no value initialization with declare… https://github.com/babel/babel/blob/f856fc22d05bf886d1a58c5c91490e1af8f90c44/packages/babel-plugin-transform-typescript/src/index.ts#L143-L148

Additional context

Real world code:

  1. https://github.com/kaiyuanshe/kaiyuanshe.github.io/pull/304/files#diff-c2eb41018a917dc350b32b5f8633d8f7cbf1737c32bb0a4b5bfe77cab13f2fa7
  2. https://github.com/kaiyuanshe/OpenHackathon-Web/pull/210/files#diff-2e17f0d5a3cb9ec641b2b936b7aaab6ac68eabb4cbc21958508ed9698b1de871R65-L73

About this issue

  • Original URL
  • State: open
  • Created 5 months ago
  • Comments: 16 (8 by maintainers)

Most upvoted comments

This is a plugin order issue and as a temporary solution you can use a configuration like this.

module.exports = {
  presets: [
    // https://babeljs.io/docs/babel-preset-react
    [
      '@babel/preset-react',
      {
        runtime: 'automatic',
        development: process.env.BABEL_ENV === 'development',
      },
    ],
  ],
  // https://babeljs.io/docs/babel-plugin-proposal-decorators#note-compatibility-with-babelplugin-transform-class-properties
  plugins: [
    [
      '@babel/plugin-transform-typescript',
      {
        allowDeclareFields: true,
        allowNamespaces: true,
        allExtensions: true,
        isTSX: true,
      },
    ],
    ['@babel/plugin-proposal-decorators', { version: '2023-05' }],
  ],
};

repl

Unfortunately I still can’t reproduce it.

You should use the old version: image