ReactでTypeScriptの型定義を拡張する

こんにちはかみむらです。最近は、React + TypeScriptをよく書いているのですが、下記のようなエラーが発生しました。

f:id:kamimura-dev:20200213152735p:plain

ここでやりたかったことは、Chromeでサポートされたimgのプロパティで、Loading Attributeを使って画像を遅延読み込みしようとしました。
Reactでも使えそうだったので実装してみたところ、imgプロパティに型定義がないと怒られました。そこでDefinitelyTypedで、imgプロパティの型定義を確認したところ、やはりありませんでした。

DefinitelyTypedから引用(2020/2/16)

f:id:kamimura-dev:20200213155220p:plain

github.com

プルリクエストを送ることも考えましたが、色々調べたところ下記のプルリクエストを見つけました。

github.com

上記リンクのコメントからの引用です。

We decided to not accept attributes that are not part of the spec. If you want to use non-standard attributes I recommend using module augmentation.

ざっくり翻訳すると、仕様の一部ではない属性を受け入れないことに決めました。非標準の属性を使用する場合は、モジュールの拡張お勧めします。とのこと。

まだ、Loading AttributeはChromeの実験的機能で、DefinitelyTypedの型定義にマージされないみたいです。なので、今回はReactの型定義を自分で拡張してみました。

想定

create-react-appで作成した、TypeScriptのプロジェクトを前提に話を進めていきます。

型定義の拡張

デフォルトでは、node_modules/@typesのパッケージが対象範囲とみなされます。 なので、typesRootsで型定義があるフォルダを指定する必要があります。 tsconfig.jsonに下記の設定を追加してください。これで、対象範囲がsrc/typesフォルダに広がりました。

tsconfig.json

 //追加
"typeRoots": ["./node_modules/@types", "src/types"]

そして、srcフォルダの中にtypesフォルダを作成して、react.d.tsを作成します。Reactをインポートして、moduleを定義します。あとはImgHTMLAttributesにLoading Attributeを追加します。

types/react.d.ts

import 'react';

declare module 'react' {
  interface ImgHTMLAttributes<T> extends HTMLAttributes<T> {
    loading?: 'lazy' | 'eager' | 'auto' | '';
  }
}

これで、imgプロパティの型定義を拡張することができました。

最後に

今回は、Reactのimgプロパティの型定義を拡張してみました。もし、型定義がない場合はこの方法を試してください。

ちなみにLoading AttributeがHTMLの標準規格になるみたいです。なので、今後型定義が追加される可能性が高いですね!今後の動向に注目です。

html.spec.whatwg.org