😢

ElementやEventに型をつけよう

2021/08/26に公開

目次

はじめに

any使っていませんか?

idが"xxx"のinput要素に入力された値を取得してみてください。

この要件を w3schools のサンプルコードをコピペして実装しようとすると、

document.getElementById("xxx").value

error.png

型エラー起きてるやんけ、、😢

対象読者

  • 上のような問題にお悩みの方
  • TypeScript 4.4

今回の目標

DOM操作で型をつけることを目標にします。

Elementについて

DOM, Node, Elementについてそれぞれの違いを説明できますか?
最近上げた記事があるので、そちらを参考にしてください。

↓↓↓

https://zenn.dev/sqer/articles/2d4def0f07bf04c5cc47

Elementといってもその中にはHTMLElementやHTMLInputElementといったものがあります。
それぞれでオブジェクト構造も違いますので、要素によって違いを把握する必要がありそうです。

対応するタグ 行える処理
Element HTMLElement
HTMLElement HTMLInputElement
HTMLInputElement Node

Eventについて

実践!TypeScriptで型付けする

ではここから、具体的に型を付けていくにはどうすればいいのか解説していきます。

typed-query-selectorを使う

https://github.com/g-plane/typed-query-selector

querySelector を利用する場合はもっとも強力な方法でしょう。
TypeScript4.1の機能である Template Literal Types を利用してquerySelectorの型推論を自動で行ってくれるからです。
以下が実際の実行例です。

document.querySelector('div#app') // ==> HTMLDivElement

document.querySelector('div#app > form#login') // ==> HTMLFormElement

document.querySelectorAll('span.badge') // ==> NodeListOf<HTMLSpanElement>

anElement.querySelector('button#submit') // ==> HTMLButtonElement

yarn add -D typed-query-selector にてインストールしたあと、tsconfig.jsonに以下を追加します

{
  "compilerOptions": {
    "types": ["typed-query-selector"] // "typed-query-selector/strict" がオススメ
  }
}

Chrome拡張のように querySelector を一度でも使うプロジェクトには入れるようにしています。

target.valueに型をつける

@types/react にあるイベント定義を利用します

type EventHandler<E extends SyntheticEvent<any>> = { bivarianceHack(event: E): void }["bivarianceHack"];

type ReactEventHandler<T = Element> = EventHandler<SyntheticEvent<T>>;

type ClipboardEventHandler<T = Element> = EventHandler<ClipboardEvent<T>>;
type CompositionEventHandler<T = Element> = EventHandler<CompositionEvent<T>>;
type DragEventHandler<T = Element> = EventHandler<DragEvent<T>>;
type FocusEventHandler<T = Element> = EventHandler<FocusEvent<T>>;
type FormEventHandler<T = Element> = EventHandler<FormEvent<T>>;
type ChangeEventHandler<T = Element> = EventHandler<ChangeEvent<T>>;
type KeyboardEventHandler<T = Element> = EventHandler<KeyboardEvent<T>>;
type MouseEventHandler<T = Element> = EventHandler<MouseEvent<T>>;
type TouchEventHandler<T = Element> = EventHandler<TouchEvent<T>>;
type PointerEventHandler<T = Element> = EventHandler<PointerEvent<T>>;
type UIEventHandler<T = Element> = EventHandler<UIEvent<T>>;
type WheelEventHandler<T = Element> = EventHandler<WheelEvent<T>>;
type AnimationEventHandler<T = Element> = EventHandler<AnimationEvent<T>>;
type TransitionEventHandler<T = Element> = EventHandler<TransitionEvent<T>>;

例えば

<input
  onChange={onChangeInput}
/>

における onChangeInputは

onChangeInput: ChangeEventHandler<HTMLInputElement> = (evt: ChangeEvent<HTMLInputElement>) => void

となってます。

まとめ

ElementやEventに型をつける方法について自分の知っている限りでいくつか紹介しました。
他にも簡単な方法を知っている方がいましたら、ぜひコメントください!

今後も型に関する様々な記事を投稿していくのでよろしくおねがいします!

リンク

Discussion