問題
Gatsby のチュートリアルを実際に書きながら学ぼうと思い、こちらのチュートリアルに倣い、<Link>
を追加した。
// Step 1: Import React
import { Link } from 'gatsby';
import * as React from 'react';
// Step 2: Define your component
const IndexPage = () => {
return (
<main>
<title>Home Page</title>
<h1>Welcome to my Gatsby site!</h1>
<Link to="/about">About</Link>
<p>I'm making this by following the Gatsby Tutorial.</p>
</main>
);
};
// Step 3: Export your component
export default IndexPage;
この状態で VSCode および yarn typecheck
を行うと以下のような型エラーが発生してしまった。
src/pages/index.tsx:11:8 - error TS2786: 'Link' cannot be used as a JSX component.
Its instance type 'GatsbyLink<unknown>' is not a valid JSX element.
11 <Link to="/about">About</Link>;
'Link' を JSX コンポーネントとして使用することはできません。
そのインスタンスの型 'GatsbyLink<unknown>' は、有効な JSX 要素ではありません。
'render()' によって返された型は、これらの型同士で互換性がありません。
型 'React.ReactNode' を型 'import("/****/node_modules/@types/reach__router/node_modules/@types/react/index").ReactNode' に割り当てることはできません。
型 '{}' を型 'ReactNode' に割り当てることはできません。ts(2786)
なお、yarn gatsby develop
では正常に動作していたため、TypeScript の型関連のエラーであると考えられる。
原因
@types/react
のバージョンアップによって、型定義変更の影響が出ているのが原因のようだ。
こちらの StackOverflow の記事にも書かれている通り、package.json
に以下の通り resolutions を追加して、バージョン18未満の @types/react
と @types/react-dom
を使うようにする。
"resolutions": {
"@types/react": "17.0.14",
"@types/react-dom": "17.0.14"
}
書き換えた後は yarn
を実行する。 書き換えの前後で yarn list
の diff を取ると、今回は以下のようになっていた。 確かに、置き換え前は @types/react のバージョン18以上を使っていたことが分かる。
1035c1035
< │ └─ @types/react@18.0.5
---
> │ └─ @types/react@17.0.14
1040c1040,1044
< │ └─ @types/react@^17
---
> │ ├─ @types/react@^17
> │ └─ @types/react@17.0.14
> │ ├─ @types/prop-types@*
> │ ├─ @types/scheduler@*
> │ └─ csstype@^3.0.2
4391c4395
最後に
原因を見れば分かるが、明らかに過渡期の問題であり将来的には収束する問題ではある。
しかし、このレベルのエラーが発生するとなると、特に(自分を含む)TypeScript の初心者はこういった過渡期の問題にたまたまあたってしまうと辛いなあと思ってしまう。
過去に nuxt の stylus-loader でも古いバージョンを指定する、という解決策をしたことがあるが、JavaScript や TypeScript では普通の文化なのだろうか…?