DOM、ネットワーク、JSON がコンパイラの目を逃れる、アプリケーションの境界で信頼できる型を保ちましょう。
このレッスンを Kodokon で開く現実のコードは、完璧な型が終わるところから始まります。DOM、ネットワーク、JSON は TypeScript が推測できないデータを返します。第一の境界は DOM です。querySelector は Element | null を返しますが、これは value を読んだり focus() を呼んだりするには曖昧すぎる型です。
const input = document.querySelector<HTMLInputElement>(
"#email"
);
if (input) {
input.value = "test@example.com";
input.focus();
}型パラメータは、あなたがコンパイラに対して交わす約束です。正しいセレクタを狙うのはあなたの責任です。要素がイベント由来のときは、実行時に型を実際に検証する instanceof チェックを選びましょう。
const form = document.querySelector("form");
form?.addEventListener("submit", (event) => {
event.preventDefault();
if (event.target instanceof HTMLFormElement) {
console.log(new FormData(event.target));
}
});第二の境界はネットワークです。response.json() は Promise<any> を返します。言い換えれば、何でも通り抜ける開いたドアです。プロとしての最低限: 期待する型を宣言し、response.ok をチェックし、呼び出しを型付きの関数に集約することです。
interface Post {
id: number;
title: string;
}
async function getPost(id: number): Promise<Post> {
const url = `https://api.example.com/posts/${id}`;
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return (await response.json()) as Post;
}この as Post は信頼の表明にすぎません。API が変わっても、実行時には何も警告してくれません。重要なデータには、使う前に JSON の実際の形を検証する型ガードを書きましょう。
function isPost(value: unknown): value is Post {
if (typeof value !== "object" || value === null) {
return false;
}
const obj = value as Record<string, unknown>;
return (
typeof obj.id === "number" &&
typeof obj.title === "string"
);
}