はじめに
Web制作の現場でTypeScriptを使う際に役立つTipsをまとめた記事です。
主にDOM操作での型エラーやAstroフレームワーク特有の型定義などをまとめています。
TypeScriptを始めたばかりの方や、これからWeb制作でTypeScriptを活用したい方の参考になれば幸いです。
目次
nullチェック
const button = document.querySelector('.button');
button.addEventListener('click', () => { ... }); // 'button' は 'null' の可能性があります。
原因
- 該当する要素が見つからない場合、
buttonはnullとなるため
解決策
- 要素が見つからない場合に実行しないようにnullチェックを行う
const button = document.querySelector('.button');
if (button) { // ✅ null チェック
button.addEventListener('click', () => {});
}
要素の型が取得できない
const button = document.querySelector('.button'); // Element | null
原因
- クラスセレクタを使用すると、TypeScriptは具体的な要素の型を推論できず、
Element | nullという汎用的な型になります
解決策
- ジェネリクスで型を指定することで任意の型とすることができます
const button = document.querySelector<HTMLButtonElement>('.button'); // HTMLButtonElement | null
// クラスセレクタではなくタグセレクタを使っても型が推論されます
const button = document.querySelector('button'); // HTMLButtonElement | null
対象要素のvalueにアクセスできない
const input = document.querySelector<HTMLInputElement>('.input');
if (input) {
input.addEventListener('change', (e) => {
console.log(e.currentTarget.value); // プロパティ 'value' は型 'EventTarget' に存在しません。
});
}
原因
-
e.currentTargetはEventTarget | nullとなるが、このEventTargetにHTMLElementの要素が必ずしもくるとは限らないため(参考リンク)
解決策
- 型ガードを利用する(推奨)
- 型アサーションでの上書き
// 型ガードの例
input.addEventListener('change', (e) => {
if (!(e.currentTarget instanceof HTMLInputElement)) {
return;
}
console.log(e.currentTarget.value);
});
// 型アサーションの例
input.addEventListener('change', (e) => {
console.log((e.currentTarget as HTMLInputElement).value);
});
Astro
任意の要素の型を適用したい場合
- Astro組み込みの
HTMLAttributesを使うことで任意の要素の型を拡張できます。(参考リンク)
---
import type { HTMLAttributes } from "astro/types";
interface Props extends HTMLAttributes<"a"> { // <a>を拡張
color?: "red" | "blue" | "green";
}
const { class: className, href, color, ...attrs } = Astro.props;
---
<a href={href} class:list={[className, color && `_${color}`]} {...attrs}>
<slot />
</a>
<Link color="red" href="/path">リンクテキスト</Link> // <a>の補完が効く
ポリモーフィックな要素を作りたい場合
- Astro組み込みの
HTMLTagと、Polymorphicを使うことで再現できます。(参考リンク)
---
import type { HTMLTag, Polymorphic } from 'astro/types';
// HTMLTagにデフォルト値を設定
type Props<Tag extends HTMLTag = 'a'> = Polymorphic<{ as: Tag }>;
// Tagにデフォルト値を設定
const { as: Tag = 'a', ...rest } = Astro.props;
---
<Tag {...rest} />
<LinkButton /> // <a>として出力される
<LinkButton as="button" /> // <button>として出力される
Extractを使うことで利用するタグの制限をかけることも可能です。
// Extractで a | button とする
type Props<Tag extends Extract<HTMLTag, 'a' | 'button'> = 'a'> = Polymorphic<{ as: Tag }>;
<LinkButton as="select" /> // 型エラー
<LinkButton /> // OK <a>
<LinkButton as="button" /> // OK <button>
まとめ
Web制作でTypeScriptを活用する際のTipsをまとめてみました。
慣れてくるとエディタの補完機能や型安全性による開発効率の向上を実感できると思います。
本記事は今後も継続的に更新していく予定です。