5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

Web制作の現場でTypeScriptを使う際に役立つTipsをまとめた記事です。
主にDOM操作での型エラーやAstroフレームワーク特有の型定義などをまとめています。
TypeScriptを始めたばかりの方や、これからWeb制作でTypeScriptを活用したい方の参考になれば幸いです。

目次

nullチェック

const button = document.querySelector('.button');
button.addEventListener('click', () => { ... }); // 'button' は 'null' の可能性があります。

原因

  • 該当する要素が見つからない場合、buttonnull となるため

解決策

  • 要素が見つからない場合に実行しないように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.currentTargetEventTarget | nullとなるが、このEventTargetHTMLElementの要素が必ずしもくるとは限らないため(参考リンク)

解決策

  • 型ガードを利用する(推奨)
  • 型アサーションでの上書き
// 型ガードの例
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をまとめてみました。
慣れてくるとエディタの補完機能や型安全性による開発効率の向上を実感できると思います。
本記事は今後も継続的に更新していく予定です。

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?