Next.js + TypeScriptでimportしたSVGの型がanyになってしまう
前提: TypeScript + Next.js + svgrでSVGをインポートする
自分の関わっているNext.js製アプリケーションでは、svgrを導入することによりSVGを他のReactコンポーネントと同じ形でimportできるようにしています。
この記事の本筋からそれますが、svgrは以下のようにNext.jsへの導入できます。
↓ インストール
$ npm install --save-dev @svgr/webpack
↓ @svgr/webpack
をWebpackのloaderとして設定します。細かな設定はsvgrのドキュメントを確認してください。
module.exports = {
webpack: (config) => {
config.module.rules.push({
test: /\.svg$/,
use: ['@svgr/webpack'],
});
return config;
},
}
↓ 他のコンポーネントと同じように扱うために*svg
の型を宣言しておきます。
declare module '*.svg' {
const content: React.FC<React.SVGProps<SVGElement>>;
export default content;
}
↓ これでSVGをimportできるようになりました。
import Icon from "./assets/icon.svg"
export const Foo = () => {
return <div><Icon widht={16} height={16} /></div>
}
本題: importしたSVGがanyになってしまう
以下Next.js v11.1.0 時点での話です。上で紹介した方法でSVGファイルをimportすると、なぜかany型として扱われてしまいます。
import Icon from "./assets/icon.svg"
👆 `<Icon />`の型がanyになってしまう
自分で書いたdeclare module '*.svg' { ... }
が反映されていないというわけです。
なぜany
になってしまうのかを追ってみると、Next.jsのnode_modules/next/image-types/global.d.ts
に同じく*.svg
への宣言がされており、そちらが優先されてしまっているようです。
// node_modules/next/image-types/global.d.ts
declare module '*.svg' {
/**
* Use `any` to avoid conflicts with
* `@svgr/webpack` plugin or
* `babel-plugin-inline-react-svg` plugin.
*/
const content: any
export default content
}
Next.jsの画像のimportについての型定義を無効にする
色々と調べてみると、公式ドキュメントに以下のような記述がありました。
Disable Static Imports
The default behavior allows you to import static files such as import icon from './icon.png and then pass that to the src property.
In some cases, you may wish to disable this feature if it conflicts with other plugins that expect the import to behave differently.
You can disable static image imports with the following configuration below.
next.config.jsmodule.exports = { images: { disableStaticImages: true, }, }
Next.jsではデフォルトでjpegやpngやsvgなどのファイルをimportできるようにするためにnext/image-types/global.d.ts
で画像ファイルに関する型定義をしてくれているようです。
Next.js v11.1.0時点ではsvgのimportはany
となっており、これが自分で書いたものより優先されてしまっていたというわけです。
自分のプロジェクトではsvg以外の画像ファイルをimportして読み込むことはないため、ドキュメントの通り設定を無効にすることにしました。
module.exports = {
images: {
disableStaticImages: true,
},
}
これで自分で用意したdeclare module '*.svg' { ... }
が効くようになりました。
Discussion
next.config.js
に対して下記のように型定義が効くように起票した場合。imagesで添付画像のようなエラーが出てしまいました。🤔
何か考えられる原因等もし知っていたらお知恵をお借りできたらと思っております。
現状は
// @ts-check
を外して対応エラーが出ないようにしてあります。▽ vs codeのエラー
型定義情報を調べたところ
ImageConfig
には、disableStaticImages がちゃんとありました...自分のプロジェクトでは
.js
ファイルを型エラーのチェック対象としていないため、ちょっと分からないですね…。ただ
ImageConfig
の型定義をimageSized
などプロパティがoptionalになっていないため、images.disableStaticImages
だけ指定すれば確かに型エラーとなるはずです。Next.js側でそのうち修正される気がしますね。
Next.jsにIssueとPRを作っておきました
確かに、必須項目部分がありますね。
見落としていました👀
issueとPRの作成ありがとうございます!
こちらマージされたので今後のリリースで修正されると思います!