環境
- yarn v3.1.1
- next v12.1.4
- react v17.0.2
- @types/react v17.0.33
背景
Next.js が自動生成する _app.tsx で下記のようなコードがある。
const App = ({ Component, pageProps }: AppProps) => (
<Component {...pageProps} />
);
export default App;
ここがある時から下記のような型エラーを吐くようになった。
'Component' cannot be used as a JSX component.
Its element type 'Component<any, any, any> | ReactElement<any, any> | null' is not a valid JSX element.
Type 'Component<any, any, any>' is not assignable to type 'Element | ElementClass | null'.
Type 'Component<any, any, any>' is not assignable to type 'ElementClass'.
The types returned by 'render()' are incompatible between these types.
Type 'React.ReactNode' is not assignable to type 'import("/Users/username/work/project-name/web/node_modules/@types/react-transition-group/node_modules/@types/react/ts5.0/index").ReactNode'.
Type '{}' is not assignable to type 'ReactNode'.ts(2786)
どうやら ReactNode を返してほしいのに {}
が返される可能性があり、それは許容できませんよと TypeScript が言っているらしい。
原因
エラー文の下から2行目を読むと、どうやら @types/react-transition-group/node_modules/
配下の @types/react
を参照しようとしている。
Type 'React.ReactNode' is not assignable to type 'import("/Users/username/work/project-name/web/node_modules/@types/react-transition-group/node_modules/@types/react/ts5.0/index").ReactNode'.
その中身を見てみると DO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_REACT_NODES
という名前で確かに {}
が ReactNode の一部に含まれている。
/**
* For internal usage only.
* Different release channels declare additional types of ReactNode this particular release channel accepts.
* App or library types should never augment this interface.
*/
interface DO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_REACT_NODES {}
type ReactNode =
| ReactElement
| string
| number
| ReactFragment
| ReactPortal
| boolean
| null
| undefined
| DO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_REACT_NODES[keyof DO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_REACT_NODES];
最近 https://github.com/DefinitelyTyped/DefinitelyTyped/pull/65220 で追加された型のようで、このファイルの冒頭を見ると // Type definitions for React 18.2
と書いてある。
つまりプロジェクトの /node_modules/@types/react 内にある ReactNode の型が期待されているのに、なぜか /node_modules/react-transition-group/node_modules/@types/react 内にある ReactNode 型が参照されており、そのバージョンが異なっているためエラーになっているものと判断できる。
ちなみに yarn.lock の @types/react-transition-group
の依存を見てみると、下記のように @types/react
のバージョンは問わないという形になっているため、 yarn install 時に最新のバージョンが入ってしまったのかと思われる。
"@types/react-transition-group@npm:^4.4.0":
version: 4.4.4
resolution: "@types/react-transition-group@npm:4.4.4"
dependencies:
"@types/react": "*"
checksum: 86e9ff9731798e12bc2afe0304678918769633b531dcf6397f86af81718fb7930ef8648e894eeb3718fc6eab6eb885cfb9b82a44d1d74e10951ee11ebc4643ae
languageName: node
linkType: hard
解決策
今回は package manager に yarn を利用しているので、その機能である resolutions
を利用するため package.json に下記を追記する。
+ "resolutions": {
+ "@types/react": "17.0.33"
+ }
こうすることで依存ライブラリ経由で参照される react
や @types/react
のバージョンを固定することができ、無事に冒頭の型エラーが消える。
ついでに next や react など、アプリケーション全体でバージョンが揃ってないとまずそうなライブラリを resolutions で固定しておくと良さそうだ。