一昨日「記事リストを10件ごと分割して表示する」機能を実装した例を紹介しました。そのコードを昨日、noImplicitAny
オプション(暗黙的なany型を許容しない)・strictNullChecks
オプション(全ての型でnull
undefined
を禁止)を有効にして書き換えてみました。書き換えたコードは記事を更新して公開しているのですが、書き換えた効果の程はいかに?と思い実際に挙動を確認してみました。
よくあるのは想定と違うHTMLになっていたとか、実装した機能を利用するページ以外でも機能が実行されたとかで要素が取得できずエラーになるケースでしょうか。開発者ツールのコンソールにエラーが出ているのはよく目にします。自分の案件ではそのようなことがないよう確認していますが、少々手間のかかる作業かもしれませんし予想できなければ見逃してしまうかもしれません。
strictNullChecks
オプションを有効にした場合、ID属性値を元にある要素を取得しさらにquerySelectorAll()
で要素を取得するコードは以下のように記述します。
const elem: HTMLElement | null = document.getElementById(id);
const list: Array<HTMLLIElement> = Array.from(elem?.querySelectorAll('[some query]') ?? []);
null
が入る可能性がある変数には型を記述するときに| null
を追記null
が入っているかもしれない変数を利用するときに?
演算子を利用
私はSwiftでコーディングをした経験があってオプショナル型はしっかり学習したので、この記述は容易に理解できました。書き換えたコードを実行すると期待通り開発者ツールのコンソールにエラーが出ることはなくなりました。strictNullChecks
オプションが有効の時、処理の返値がnull
になる可能性があるのに| null
が書かれていない部分等はコンパイル時にエラーになるので、開発者ツールにエラーが表示されるようなコードはほぼ排除できそうです。(この変数も| null
か| undefined
が必要なのでは?というケースが1箇所ありました。)
コンパイルされたコードはどのようになっているのだろうと確認してみると、しっかりnull
であるか否かのチェックが入っていました。(this
が入っているのは一昨日のブログ記事に掲載のコードを変換しているためです。)これが?
演算子1つで書けるのはとても助かります。
list = Array.from((_b = (_a = this.elem) === null || _a === void 0 ? void 0 : _a.querySelectorAll(this.options.listItemQuery)) !== null && _b !== void 0 ? _b : []);
Web APIの返値は読みやすいところではMDNに書かれています。例えばDocument.getElementById()
です。
指定された ID に一致する DOM 要素オブジェクトを記述した Element オブジェクト、または文書内に一致する要素がなければ null です。
TypeScriptのnoImplicitAny
オプション・strictNullChecks
オプションを有効活用して、より品質の高いコードを書いていきたいと考えました。