Gardez des types fiables aux frontières de votre application, là où le DOM, le réseau et le JSON échappent au compilateur.
Ouvrir cette leçon dans KodokonLe code réel commence là où les types parfaits s'arrêtent : le DOM, le réseau et le JSON renvoient des données que TypeScript ne peut pas deviner. Premier terrain : le DOM. querySelector retourne Element | null, un type trop vague pour lire value ou appeler focus().
const input = document.querySelector<HTMLInputElement>(
"#email"
);
if (input) {
input.value = "test@example.com";
input.focus();
}Le paramètre de type est une promesse que vous faites au compilateur : à vous de viser le bon sélecteur. Quand l'élément provient d'un événement, préférez une vérification instanceof, qui contrôle réellement le type à l'exécution.
const form = document.querySelector("form");
form?.addEventListener("submit", (event) => {
event.preventDefault();
if (event.target instanceof HTMLFormElement) {
console.log(new FormData(event.target));
}
});Deuxième frontière : le réseau. response.json() renvoie Promise<any>, autrement dit la porte ouverte à n'importe quoi. Le minimum professionnel : déclarer le type attendu, vérifier response.ok et centraliser l'appel dans une fonction typée.
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;
}Le as Post reste une déclaration de confiance : si l'API change, rien ne vous alerte à l'exécution. Pour les données critiques, écrivez un type guard qui valide la forme réelle du JSON avant de l'utiliser.
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"
);
}