🧞‍♂️

「'Component' を JSX コンポーネントとして使用することはできません」を対処してみた【Next.js+Typescript】

2023/08/12に公開

環境

パッケージマネージャー: yarn

"@types/react": "18.2.6",
"@types/react-dom": "18.2.6",
"next": "13.4.2",
"typescript": "5.0.4"
"react": "18.2.0",
"react-dom": "18.2.0",

発生した問題

Next.jsプロジェクトを作成すると _app.tsx というファイルが生成されます(以下例)

const App = ({ Component, pageProps }: AppProps) => (
  <Component {...pageProps} />
);

export default App;

この Component の部分で以下のようなエラーが発生しました。

'Component' を JSX コンポーネントとして使用することはできません。
  その要素の型 'ReactElement<any, any> | Component<{}, any, any> | null' は有効な JSX 要素ではありません。
    型 'Component<{}, any, any>' を型 'Element | ElementClass | null' に割り当てることはできません。
      型 'Component<{}, any, any>' を型 'ElementClass' に割り当てることはできません。
        'render()' によって返された型は、これらの型同士で互換性がありません。
          型 'React.ReactNode' を型 'import("/Users/user_name/workspace/project/node_modules/@types/react-dom/node_modules/@types/react/index").ReactNode' に割り当てることはできません。
            型 'ReactElement<any, string | JSXElementConstructor<any>>' を型 'ReactNode' に割り当てることはできません。
              プロパティ 'children' は型 'ReactElement<any, string | JSXElementConstructor<any>>' にありませんが、型 'ReactPortal' では必須です。ts(2786)
index.d.ts(198, 9): 'children' はここで宣言されています。

調査フェイズ

エラー内容を見る限り、どうやら /Users/user_name/workspace/project/node_modules/@types/react-dom/node_modules/@types/react/indexが怪しいっぽい。

早速対象のファイルを見てみました。

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];

...

interface ReactPortal extends ReactElement {
        key: Key | null;
        children: ReactNode;
    }

弱小エンジニアには、何がおかしいのかさっぱり分かりません。
そこで弱小エンジニアの頼れるメンター、ChatGPTさんに質問をしてみました。

◉質問

以下のようなエラーが出ました

---

'Component' を JSX コンポーネントとして使用することはできません。
  その要素の型 'ReactElement<any, any> | Component<{}, any, any> | null' は有効な JSX 要素ではありません。
    型 'Component<{}, any, any>' を型 'Element | ElementClass | null' に割り当てることはできません。
      型 'Component<{}, any, any>' を型 'ElementClass' に割り当てることはできません。
        'render()' によって返された型は、これらの型同士で互換性がありません。
          型 'React.ReactNode' を型 'import("/Users/user_name/workspace/project/node_modules/@types/react-dom/node_modules/@types/react/index").ReactNode' に割り当てることはできません。
            型 'ReactElement<any, string | JSXElementConstructor<any>>' を型 'ReactNode' に割り当てることはできません。
              プロパティ 'children' は型 'ReactElement<any, string | JSXElementConstructor<any>>' にありませんが、型 'ReactPortal' では必須です。ts(2786)
index.d.ts(198, 9): 'children' はここで宣言されています。

---

何が原因でしょうか?

◉回答(一部抜粋)

エラーメッセージをよく見ると、型の衝突が発生しているようです。特に問題となっている部分は、プロジェクトのローカルの型定義と @types/react との間で型が合わないようです。

このエラーを解消するための一般的な対処法は以下の通りです:

1. 型定義の整合性を確認する: 型定義が正しく一致しているか確認してみてください。場合によっては、型エイリアスやインターフェイスで明示的に型を定義すると良いかもしれません。
2. 依存ライブラリのバージョンを確認する: 依存ライブラリのバージョンに互換性の問題がある場合があります。特に @types/react や Next.js のバージョンを確認し、必要であればアップデートしてみてください。
3. 型のキャストを使用する: あまり推奨される方法ではありませんが、最終手段として型アサーションを使って明示的に型をキャストすることも考えられます。

良さげな回答をいただいたような気が。気になったのはこの箇所です。

依存ライブラリのバージョンを確認する: 依存ライブラリのバージョンに互換性の問題がある場合があります。特に @types/react や Next.js のバージョンを確認し、必要であればアップデートしてみてください。

基本的に色んなサイトに書いてあるような鉄板パターンでインストールをしていたつもりなので、バージョン違いとか起きないような気がー🤔なんてことを思っていました。

が、よくよくエラー文見てみると、エラーが発生しているファイルのパスが気持ち悪いことに気付きました。

"/Users/user_name/workspace/project/node_modules/@types/react-dom/node_modules/@types/react/index"

@types/react-dom の中に更に node_modules/@types/reactになってますね。そもそも @types/react-dom と同階層に @types/react は存在するんです。なのになぜ掘ったところにまた存在するの?

嫌な予感がしたので、バージョンが記載されているであろう package.json を覗いてみることにしました。

まずは @types/react-dom

{
    "name": "@types/react-dom",
    "version": "18.2.6",
    "description": "TypeScript definitions for React (react-dom)",
...
}

大丈夫ですね。次に @types/react-dom/node_modules/@types/react

{
    "name": "@types/react",
    "version": "18.2.7",
    "description": "TypeScript definitions for React",
...
}

_人人人人人人人人人人_
>絶対にこれじゃん^^<
 ̄Y^Y^Y^Y^Y^Y^Y^Y^ ̄

解決策

今回の問題点は、既に18.2.6@types/reactをインストールしていたはずだったのに、@types/react-domを使うために勝手に18.2.7@types/reactがインストールされてしまって、「バージョン違くないですか?」という問題が起きていたと推測。

そのため依存パッケージのバージョンを固定する必要があると思い、調べてみたところ、resolutions というものがあるみたいです。
ただしこれはyarn専用なので、もしnpmの方がいる場合はoverridesを使ってみると良いそうです。

早速以下をルート配下の package.jsonに追記してみました。

"resolutions": {
  "@types/react": "18.2.6"
}

そして node_modulesyarn.lockを削除し、yarnを再実行してみると...

無事発生していたエラーは解消されました🫶

まとめ

自分が想定もしていないパッケージが勝手に依存関係でインストールされていることがあるので、エラーが発生しているファイルだけでなく、パスなんかも気にしてみると解決できる確率高まりそうですね。

GitHubで編集を提案

Discussion