こんにちは、エンジニア職の id:nanto_vi です。(この記事は、はてなエンジニア Advent Calendar 2020 の 12 日目の記事です。昨日は id:cohalz さんによる「Webサービスのモニタリングについてのチェックリスト」でした。)
結論
TypeScript で querySelector
、querySelectorAll
メソッドを呼び出すときは、型引数を指定しましょう (メソッド名の直後の < >
で囲んだ部分です)。
const foo = document.querySelector<HTMLElement>('.foo'); if (foo) { foo.style.display = ''; } const bars = document.querySelectorAll<HTMLInputElement>('input[name="bar"]'); bars.forEach((bar) => { console.log(bar.value); });
解説
querySelector
メソッド
皆さんは TypeScript を書いていて、以下のようなエラーに遭遇したことはありませんか?
const foo = document.querySelector('.foo'); if (foo) { foo.style.display = ''; // Property 'style' does not exist on type 'Element'. }
style
プロパティが存在しないと言われています。変数 foo
は Element
型であり、style
プロパティが定義されているのは HTMLElement
型 (Element
型を継承している) なので、型定義上は確かに style
プロパティにアクセスできませんね。
では変数 foo
を HTMLElement
型にすればよいと以下のようなコードを書いてしまうと……
// Bad const foo = document.querySelector('.foo') as HTMLElement;
これはいけません! これだと Element | null
型から HTMLElement
型にキャストすることになり、nullability が除去されてしまいます。このままコードを書き続けると、要素が見つからないときに実行時エラーを引き起こしかねません。
// Good const foo = document.querySelector<HTMLElement>('.foo');
上記のように型引数を指定することで、querySelector
メソッドの返り値が HTMLElement | null
型となり、style
プロパティにもアクセスできるようになります。
「この要素は絶対存在するから nullability を除去したい」というときは後置 !
演算子を使いましょう。
querySelectorAll
メソッド
querySelectorAll
メソッドも同様に型引数を指定できます。型引数を指定することで、配列に変換したり forEach
メソッドを使ったりしたときに、適切な型が推論されるようになります。
const bars = document.querySelectorAll<HTMLInputElement>('input[name="bar"]'); // ここで bars は NodeListOf<HTMLInputElement> 型 bars.forEach((bar) => { // ここで bar は HTMLInputElement 型 console.log(bar.value); });
要素名からの型推論
querySelector
、querySelectorAll
メソッドでは、引数が要素名そのままのときに適切な型が推論されます。
// ここで anchor は HTMLAnchorElement | null 型 const anchor = document.querySelector('a'); // ここで buttons は NodeListOf<HTMLButtonElement> 型 const buttons = document.querySelectorAll('button');
クラスセレクタなどをつけてしまうと、要素名からの型推論は働きません。
// ここで fooAnchor は Element | null 型 const fooAnchor = document.querySelector('a.foo');
要素と型との対応
a
要素は HTMLAnchorElement
型であるといった対応は、MDN の HTML 要素リファレンスから調べられます。調べたい要素のページに飛び、「DOM インターフェイス」という項目を探してください。
もちろん、おおもとの仕様書である HTML Living Standard にも書かれています。