TypeScript: TS files cannot use JSX components declared as a classes in JS/JSX file
CC @donataswix
It appears that using a React component written as a class in a .js
file causes some issues.
Start a project with the following files:
tsconfig.json
{
"compilerOptions": {
"module": "es2015",
"target": "esnext",
"jsx": "react-native",
"strictNullChecks": true,
"allowSyntheticDefaultImports": true,
"allowJs": true,
"lib": [
"es5",
"es6",
"es7",
"es2017",
"dom"
],
"outDir": "dist"
},
"include": [
"**/*.ts",
"**/*.tsx"
],
"exclude": [
"node_modules"
]
}
index.tsx
import React from 'react';
import Hello from './hello';
class A extends React.Component<void,void> {
render() {
return (
<div>
<Hello/>
</div>
);
}
}
hello.js
import React from 'react';
export default class Hello extends React.Component {
render() {
return <div>Hello</div>;
}
}
Expected: No problems
Actual: Error on <Hello />
: JSX element type ‘Hello’ does not have any construct or call signatures.
Note that if you add type arguments to Component
in hello.js
, this will actually fix the problem (while creating new ones).
Potentially related is #13609.
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 1
- Comments: 38 (13 by maintainers)
Commits related to this issue
- Add temp workaround for Microsoft/TypeScript#14558 — committed to nkanderson/rustw-frontend by nkanderson 7 years ago
- Add temp workaround for Microsoft/TypeScript#14558 — committed to rust-dev-tools/cargo-src by nkanderson 7 years ago
- Legg til ekspanderbart nedtrekkspanel for visittkort Det er dratt inn fra nav-frontend-moduler. Per nå så opplever jeg litt krøll med komponenten, sannsynligvis fordi den ikke er skrevet i React. Int... — committed to navikt/modiapersonoversikt by deleted user 6 years ago
Helps for me
Can we please reopen it? It doesn’t work if component have any props inside and it’s a show stopper for React projects which are migrating to TypeScript
+1 I have the same problem guys
This is killing me trying to migrate a large project to Typescript. I’ve got a hundred plain ol React components and I’d love to be able to do 1 at a time, but once converted to .tsx, they can’t import any other .js files without this error.
So we know the root cause of this issue -
React
’s type definitions have their defaultProps
andState
types set to{}
- the intention being that this gives you safety; if you specify the generics, then you can access props and state safely, otherwise you get no props or state (other than what you may inherit from intrinsics). The downside to this is that in JS, you often don’t or can’t specify the generic arguments - so they default to{}
(whereas previous they defaulted toany
), and you can’t do anything with the props or state without an error. In short, React’s types used to defaultopen
, but now defaultclosed
. This behavior is arguably better for TS users, but is without a doubt a showstopper for JS users relying gradual typing with the same types. We’re trying to come up with a solution that can satisfy both user-bases, but it’s difficult.While we work on it, a workaround in the meantime is editing the
react.d.ts
to useany
for its’ default props and state types (the replacement would be this:interface Component<P = any, S = any> extends ComponentLifecycle<P, S> { }
), or adding JSDoc arguments to your JS components to specify their props and/or state types (which you should consider preferred if it is easy, as when you migrate the file to TS we provide a bunch of quick fixes to translate that JSDoc into proper TS code), for example:sadly also suffering from this issue – is a huge deal when trying to migrate incrementally to typescript.
I ran into this as well… while using
react-select
with latest typings. Has this issue been fixed in TS2.6.2
?This works for me:
We have a fix on the compiler side in https://github.com/Microsoft/TypeScript/pull/19977 to accommodate the react changes. Can you give tomorrow’s
typescript@next
a try?@mhegazy any update here? I’m in a similar boat to @z0d14c in which this makes adopting ts in a large codebase very difficult.
@weswigham can you take a look here. unfortunately we can not remove the defaults from react definition file as that would be a big breaking change, but what can we do not make sure this scenario still works.