TypeScript : satisfies
Dans cet article, nous allons voir comment tirer parti de l’opérateur satisfies
introduit avec la version 4.9 de TypeScript.
Pour mieux comprendre comment à quoi sert l’opérateur satisfies
, nous allons étudier un problème concret.
Challenge
Soit un type Status
qui définit le statut d’une requête HTTP. Pour le moment, ses valeurs possibles sont :
FAILED
: la requête a échoué.PENDING
: la requête est en cours.RESOLVED
: la requête a réussi.
Dans le code, ça donne quelque chose comme ça :
type Status = 'FAILED' | 'PENDING' | 'RESOLVED';
Soit un objet nommé i18n
qui a pour clés les différents statuts possibles et pour valeur les traductions françaises associées à ces statuts.
const i18n = { FAILED: 'Échec', PENDING: 'En cours', RESOLVED: 'Succès',};
Notre challenge est de typer l’objet i18n
de la meilleure des manières possibles, c’est-à-dire :
- le plus spécifiquement possible à la fois pour les clés et pour les valeurs.
- et en utilisant au maximum l’inférence de type.
Tentatives de solution
Essayons de typer notre objet i18n
progressivement.
as const
Pour typer les valeurs de l’objet i18n
qu’on a défini plus haut en utilisant au maximum l’inférence de type, rajoutons le mot clé as const
comme suit :
const i18n = { FAILED: 'Échec', PADDING: 'En cours', RESOLVED: 'Succès',} as const;
// ^ i18n est de type : { readonly FAILED: 'Échec'; readonly RESOLVED: 'Succès'; readonly PADDING: 'En cours' };
Les valeurs sont maintenant typées le plus spécifiquement possible. Cependant, actuellement cet objet n’est aucunement lié au type Status
.
D’ailleurs, il contient une erreur. J’ai volontairement mis PADDING
au lieu de PENDING
.
Utilisation d’un Record
Nous pouvons utiliser un Record
pour nous assurer du typage des clés de notre objet i18n
.
type Status = 'FAILED' | 'PENDING' | 'RESOLVED';
const i18n: Record<Status, string> = { FAILED: 'Échec', PENDING: 'En cours', RESOLVED: 'Succès',} as const;
// ^ i18n est de type : Record<"FAILED" | "PENDING" | "RESOLVED", string>
Les clés ont maintenant les bons types.
Cependant, le typage spécifique de notre objet (avec Record<Status, string>
) l’emporte sur l’inférence de type (avec as const
).
On perd donc le typage précis des valeurs qui deviennent toutes des string
.
La solution avec satisfies
La solution est d’utiliser le mot clé satifies
comme suit pour avoir le meilleur typage à la fois des clés et des valeurs :
type Status = 'FAILED' | 'PENDING' | 'RESOLVED';
const i18n = { FAILED: 'Échec', PENDING: 'En cours', RESOLVED: 'Succès',} as const satisfies Record<Status, string>;
// ^ i18n est de type : {readonly FAILED: "Échec", readonly RESOLVED: "Succès", readonly PENDING: "En cours"}
L’opérateur satifies
permet d’imposer une contrainte à une variable sans changer son type.
satisfies Record<Status, string>
impose donc à notre objet i18n
d’avoir des clés de type Status
.
Combiné avec as const
, notre objet i18n
devient fortement typé au niveau des clés, mais aussi des valeurs.
Conclusion
Introduit avec la version 4.9, l’opérateur satisfies
est une excellente addition au langage TypeScript qui nous offre
un outil de plus pour mieux typer nos objets TypeScript.
Vous aimez ce blog ?
Suivez-moi sur Twitter pour plus de contenu !
Rejoignez la newsletter pour du contenu de grande qualité dans votre boite mail