Typescript+Next.js+MaterialUIで詰まる

 リンクを貼りたいだけなのに…の巻

このブログの React UI コンポーネントにはMaterialUIを使用しています。 Next.js 公式のブログのひな形サンプル blog-starter-typescriptTailwindCSSを使っており、HTML の構造に引きずられることなく好きなスタイルが自分で作れる…! という事を売りにしているようなのですが、今はデザインに凝りたくはないので コンポーネント並べるだけでええ感じにしてくれるらしい MaterialUI を使うことにしました。 (お気づきの方もおらえるかも知れませんが jQuery 時代は bootstrap 大好きでした…)

Next.js のプロジェクトに MaterialUI を組み込む方法はこちらの記事を参考にしました。

ところが、npm run devでは一応表示されるのにnpm run buildを実行すると下記エラーが出てしまいなかなか解決できませんでした。

Type error: Type '{ children: Element; as: string; href: string; passHref: true; }' is not assignable to type 'IntrinsicAttributes & RefAttributes<any>'.
  Property 'children' does not exist on type 'IntrinsicAttributes & RefAttributes<any>'.

  29 |           {posts.map((post) => (
  30 |             <li key={post.filePath}>
> 31 |               <Link
     |                ^
  32 |                    as={`/posts/${post.filePath.replace(/\.mdx?$/, '')}`}
  33 |                    href={`/posts/[slug]`}
  34 |                    passHref

色々検索していると、型の不一致の時に出るエラーのようです。 React.forwardRef() のジェネリクスにちゃんと正しい型を指定すれば…と思ってさらに色々検索した結果、 こちらの issue に書かれていたコードが参考になりました。

以上を踏まえて、Link コンポーネントのソースの 拡張子を tsx に変更した上で、以下の修正を行いました。

修正前

const NextComposed = React.forwardRef(function NextComposed(props, ref) {
  :
});
  :
export default React.forwardRef((props, ref) => <Link {...props} innerRef={ref} />);

修正後

import { Link as RouterLink, LinkProps as RouterLinkProps } from "react-router-dom";
  :
const NextComposed = React.forwardRef<HTMLAnchorElement, RouterLinkProps>(function NextComposed(props, ref) {
  :
});
  :
export default React.forwardRef<HTMLAnchorElement, RouterLinkProps>((props, ref) => <Link {...props} innerRef={ref} />);

これで npm run build が通るようになりました。React.js/Next.js なんもわからん…。

文責:ともたこ/Tomotaka Ogino Twitter/github/Qiita