Skip to content

Typescript declare field causes transpile to fail #8918

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
benwiles1 opened this issue Apr 27, 2020 · 19 comments
Open

Typescript declare field causes transpile to fail #8918

benwiles1 opened this issue Apr 27, 2020 · 19 comments

Comments

@benwiles1
Copy link

Describe the bug

Using typescript declare to fix the type of the context field in class components causes the build to fail with

./src/App.tsx
SyntaxError: C:\Users\wiles\Documents\git\broken-cra\src\App.tsx: TypeScript 'declare' fields must first be transformed by @babel/plugin-transform-typescript.
If you have already enabled that plugin (or '@babel/preset-typescript'), make sure that it runs before any plugin related to additional class features:
 - @babel/plugin-proposal-class-properties
 - @babel/plugin-proposal-private-methods
 - @babel/plugin-proposal-decorators
  10 | class MyComponent extends React.Component {
  11 |   static contextType = MyContext;
> 12 |   declare context: React.ContextType<typeof MyContext>;
     |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  13 | 
  14 |   render() {
  15 |     return <span>{this.context.data || "No context"}</span>;

Did you try recovering your dependencies?

Yes

npm --version
6.14.4

Which terms did you search for in User Guide?

typescript declare transpile

Environment

npx create-react-app --info
npx: installed 98 in 23.993s

Environment Info:

  current version of create-react-app: 3.4.1
  running from C:\Users\wiles\AppData\Roaming\npm-cache\_npx\2632\node_modules\create-react-app

  System:
    OS: Windows 7 6.1.7601
    CPU: (8) x64 Intel(R) Core(TM) i7-2820QM CPU @ 2.30GHz
  Binaries:
    Node: 12.16.1 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.4 - C:\Program Files (x86)\Yarn\bin\yarn.CMD
    npm: 6.14.4 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Internet Explorer: 11.0.9600.18123
  npmPackages:
    react: ^16.13.1 => 16.13.1
    react-dom: ^16.13.1 => 16.13.1
    react-scripts: 3.4.1 => 3.4.1
  npmGlobalPackages:
    create-react-app: Not Found

Steps to reproduce

  1. Add the following component to a React hierarchy
interface MyContextValue {
  data?: string;
}
const MyContext = React.createContext<MyContextValue>({});

class MyComponent extends React.Component {
  static contextType = MyContext;
  declare context: React.ContextType<typeof MyContext>;

  render() {
    return <span>{this.context.data || "No context"}</span>;
  }
}
  1. Try to build the app with npm start or npm run build

Expected behavior

That the build will succeed

Actual behavior

Build fails with

./src/App.tsx
SyntaxError: C:\Users\wiles\Documents\git\broken-cra\src\App.tsx: TypeScript 'declare' fields must first be transformed by @babel/plugin-transform-typescript.
If you have already enabled that plugin (or '@babel/preset-typescript'), make sure that it runs before any plugin related to additional class features:
 - @babel/plugin-proposal-class-properties
 - @babel/plugin-proposal-private-methods
 - @babel/plugin-proposal-decorators
  10 | class MyComponent extends React.Component {
  11 |   static contextType = MyContext;
> 12 |   declare context: React.ContextType<typeof MyContext>;
     |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  13 | 
  14 |   render() {
  15 |     return <span>{this.context.data || "No context"}</span>;

Reproducible demo

https://github.com/benwiles1/broken-cra

@ekilah
Copy link

ekilah commented May 1, 2020

also experiencing this in a very-recently-ejected app

@stale
Copy link

stale bot commented May 31, 2020

This issue has been automatically marked as stale because it has not had any recent activity. It will be closed in 5 days if no further activity occurs.

@stale stale bot added the stale label May 31, 2020
@ekilah
Copy link

ekilah commented May 31, 2020

this is still an issue afaik

@stale stale bot removed the stale label May 31, 2020
@synchronos-t
Copy link

Yes, still an issue. And possibly this is the issue that also prevents from using this.context in the constructor. It seems that if I use the old syntax (context!: React.ContextType<typeof FooContext>;), the call to super(props, context) doesn't set this.context for the remainder of the constructor for some reason (but still works after the constructor). I tried to use the declare syntax to try if it'd work, as I assume the problem is in the TypeScript magic setting the class properties, but stuck on this Babel problem.

I can work around this problem by either using the context parameter directly from the constructor parameters or by using it in componentDidMount(), but I assume the this.context usage in constructor should be allowed as well. (That is, assuming using the declare would change the TS compilation result. If not, then that's a separate issue.)

@pekala
Copy link

pekala commented Jun 29, 2020

I think the fix is something along the lines of #9235 This worked for my non-CRA project suffering from the same issue.

@NSExceptional
Copy link

@pekala Your PR looks great! What can I change in my existing CRA project to get it to work? I'm not familiar with how this is all set up, but I don't see anything about Babel at all in the root of my project; is preset-typescript already being used somewhere in it?

@pekala
Copy link

pekala commented Jul 20, 2020

CRA hides and manages those for you, so unless you want to eject or play around with something like Craco, you have to wait for that PR to land.

@kwilkins
Copy link

Would be great to see this fixed, not really able to use Context API at this point in my typescript project :/

@SleepWalker
Copy link

I've tried to fix it with craco, but it looks like this won't work. Probably because preset must be applied at the top of config, before any other presets.

@stale
Copy link

stale bot commented Sep 20, 2020

This issue has been automatically marked as stale because it has not had any recent activity. It will be closed in 5 days if no further activity occurs.

@stale stale bot added the stale label Sep 20, 2020
@NSExceptional
Copy link

@pekala At a deeper level, how does that work, though? Does CRA use a hidden config file in the resulting project, or… what?

More curious about the implementation than anything else

@stale stale bot removed the stale label Sep 21, 2020
@stale
Copy link

stale bot commented Dec 19, 2020

This issue has been automatically marked as stale because it has not had any recent activity. It will be closed in 5 days if no further activity occurs.

@stale stale bot added the stale label Dec 19, 2020
@lucaslcode
Copy link

I have also encountered this. I am implementing an error boundary which has to be a class component and need to use my app's context.

@stale stale bot removed the stale label Dec 21, 2020
@dongjinc
Copy link

dongjinc commented May 14, 2021

I also meet this question,It's via babel plugins add -> @babel/plugin-transform-typescript and options -> "allowDeclareFields": true
the following my .babelrc file

{
 "presets": [
    "react-app"
  ],
  "plugins": [
    [
      "@babel/plugin-transform-typescript",
      {
        "allowDeclareFields": true
      }
    ]
  ]
}

will need -> yarn add @babel/plugin-transform-typescript -D

@mylnikovD
Copy link

Hey guys, just encountered this issue myself, can we hope this to be fixed soon?

@ShishKabab
Copy link

The actual fix after ejecting seems to be simple:
https://github.com/ShishKabab/react-scenario-replays-boilerplate/commit/b6fd9352504e15348d3f85ed93bc6c7b7456e424

I can't tell if this fix would break anything for anyone else though if it's integrated into the Typescript template. If anyone can verify that, I can create a PR for it.

@itsjohncs
Copy link

You can work around this using CRACO. I'll share my configuration, but first a warning: I barely understand web pack's configuration and figured this out through trial and error. Be wary.

// craco.config.js

const {
    loaderByName,
    getLoader,
} = require("@craco/craco");

module.exports = {
    webpack: {
        configure: function (webpackConfig) {
            const babelLoader = getLoader(
                webpackConfig,
                loaderByName("babel-loader")
            ).match.loader;
            babelLoader.options.presets.push([
                "@babel/preset-typescript",
                {allowDeclareFields: true},
            ]);

            return webpackConfig;
        }
    }
};

@dprockcreative

This comment was marked as duplicate.

@Xandaros
Copy link

Xandaros commented Jan 9, 2023

Is there a workaround without ejecting or additional dependencies? If you leave out the declaration it is literally telling you to add it, but it can't actually be used...

doofmars added a commit to doofmars/spotiguess that referenced this issue Feb 9, 2023
The suggested usage of using:
`declare context: React.ContextType<typeof HostContext>`
is not working due to the open issue:
facebook/create-react-app#8918
During build the flowing error is blocking:
`'declare' fields must first be transformed by @babel/plugin-transform-typescript`

As there is no proper workaround the decision was made
to pass props instead.
doofmars added a commit to doofmars/spotiguess that referenced this issue Feb 9, 2023
The suggested usage of using:
`declare context: React.ContextType<typeof HostContext>`
is not working due to the open issue:
facebook/create-react-app#8918
During build the flowing error is blocking:
`'declare' fields must first be transformed by @babel/plugin-transform-typescript`

As there is no proper workaround the decision was made
to pass props instead.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment