Vous maîtrisez les mécanismes de rétrécissement de type et écrivez vos propres prédicats pour fiabiliser les unions.
Ouvrir cette leçon dans KodokonLe narrowing est le mécanisme par lequel TypeScript affine un type large (une union, unknown) vers un type plus précis en analysant le flux de contrôle. Vous l'utilisez déjà sans y penser : chaque if sur une valeur typée déclenche une analyse. Le compilateur suit trois familles de gardes natifs : typeof pour les primitives, instanceof pour les instances de classes, et in pour la présence d'une propriété. Bien les choisir évite les casts sauvages avec as, qui désactivent la vérification au lieu de la guider.
function formatValue(
value: string | number | Date
): string {
if (typeof value === "string") {
return value.trim();
}
if (value instanceof Date) {
return value.toISOString();
}
return value.toFixed(2);
}L'opérateur in est précieux quand vous manipulez des objets structurellement différents sans champ discriminant. Attention toutefois : in teste la présence d'une clé, y compris héritée, pas son type. Sur des données externes (API, JSON), il rétrécit selon vos déclarations, pas selon la réalité à l'exécution. Le piège classique du métier : un typeof value === "object" laisse passer null, car typeof null vaut "object" en JavaScript. Ajoutez toujours un test de nullité explicite.
interface Cat { meow(): void }
interface Dog { bark(): void }
function speak(animal: Cat | Dog): void {
if ("meow" in animal) {
animal.meow();
} else {
animal.bark();
}
}Quand la logique de garde devient réutilisable ou trop complexe pour l'analyse de flux, écrivez un type guard personnalisé : une fonction dont le retour est annoté value is T. Le compilateur fait alors confiance à votre implémentation. C'est un contrat : si votre test est incomplet, vous réintroduisez des erreurs à l'exécution que le typage ne verra jamais. Depuis TypeScript 5.5, les prédicats simples sont inférés automatiquement dans les callbacks comme filter, mais l'annotation explicite reste la norme pour les fonctions exportées.
interface User { id: string; email: string }
function isUser(value: unknown): value is User {
return (
typeof value === "object" &&
value !== null &&
"id" in value &&
typeof value.id === "string" &&
"email" in value &&
typeof value.email === "string"
);
}
const raw: unknown =
JSON.parse('{"id":"1","email":"a@b.c"}');
if (isUser(raw)) {
console.log(raw.email.toLowerCase());
}typeof value === "object" est-il insuffisant pour rétrécir vers un objet non nul ?booleanvalue as Uservalue is Userasserts value