Skip to content
tutorials

La mise à niveau Effect qui rend les échecs visibles

Une `Promise<User>` propre peut masquer les échecs qui font tomber les services en production. Le plus surprenant : ajouter de la sécurité peut rendre vos types plus informatifs, et non plus complexes.

Marcus Lee
La mise à niveau Effect qui rend les échecs visibles

Le type Promise a un angle mort en production

Imaginez un contrat courant dans votre base de code : Promise<User>. Ce type décrit parfaitement le scénario idéal : vous attendez un objet User si tout se passe bien. Mais qu'en est-il du monde réel ? Il ne dit rien sur une erreur HTTP, un utilisateur manquant ou une requête qui reste indéfiniment en attente, laissant votre application bloquée.

TypeScript, malheureusement, ne type pas de manière fiable les rejets de promesses. Vos gestionnaires catch reçoivent souvent une valeur unknown, vous obligeant à deviner à l'exécution ce qui a mal tourné. Cela signifie que les équipes perdent un temps précieux à établir les comportements en cas d'échec par essais et erreurs, plutôt que par des vérifications robustes du compilateur.

Considérez un service qui récupère des profils utilisateur. Les appelants ont besoin de plus qu'un simple User ou une erreur non typée. Ils doivent savoir s'ils doivent réessayer automatiquement la requête (comme pour un problème réseau transitoire), afficher un message clair "utilisateur non trouvé" ou arrêter d'attendre après un délai spécifique. Sans cette clarté dans vos types, votre environnement de production devient un angle mort, masquant des informations cruciales sur les raisons des échecs.

Effect ajoute les éléments manquants au contrat

Effect transforme le contrat de Promise<User> en quelque chose de plus robuste. Sa signature principale est Effect<A, E, R>, qui décrit précisément trois aspects cruciaux de toute exécution : la valeur de succès, l'échec typé et toutes les dépendances requises.

Analysons cela. A représente la valeur obtenue en cas de succès, comme User dans notre exemple. E est là où la magie opère pour les échecs, en fournissant une union typée de toutes les erreurs attendues, telles que HttpError | NotFound. Enfin, R signifie "requirements" (exigences) — les services ou dépendances dont le code a besoin pour s'exécuter, comme un client HTTP ou une connexion à une base de données.

Considérez notre fonction de recherche d'utilisateur de la vidéo. Au lieu d'un simple Promise<User>, son type Effect pourrait être Effect<User, HttpError | NotFound, SomeHttpClient>. Cela rend le contrat explicite : il vous indique non seulement que vous pourriez obtenir un User, mais aussi qu'une HttpError ou une condition NotFound sont des modes d'échec spécifiques et attendus.

C'est une grande différence par rapport à une promesse ordinaire. Les exécutions Effect sont des valeurs paresseuses (lazy values), ce qui signifie qu'elles décrivent quoi faire, mais pas quand le faire. Vous composez toute votre exécution, y compris les tentatives, les délais d'attente et les politiques de gestion des erreurs, avant l'exécution. Cela garde toutes les exigences et les résultats potentiels visibles pendant que vous construisez votre programme, transformant un angle mort en une carte détaillée.

Regardez le type d'erreur changer à mesure que vous ajoutez de la sécurité

Traçons l'évolution du type d'erreur à mesure que nous ajoutons de la résilience à un pipeline de récupération de données. Initialement, notre Effect<User, HttpError | NotFound, R> peut échouer avec soit une HttpError, soit une erreur NotFound.

D'abord, nous appliquons une politique de nouvelle tentative exponentielle pour gérer les HttpError transitoires, mais cela ne change pas la signature du type car les tentatives n'éliminent pas la possibilité d'une HttpError. Ensuite, nous ajoutons un délai d'attente de deux secondes. Cela introduit immédiatement TimeoutError dans notre type d'erreur, le transformant en Effect<User, HttpError | NotFound | TimeoutError, R>.

Ensuite, nous gérons explicitement le cas NotFound en fournissant une valeur de repli. Comme par magie, le type NotFound disparaît de notre signature d'erreur car il est désormais garanti d'être géré. Notre type devient Effect<User, HttpError | TimeoutError, R>. Ce n'est pas juste une astuce intelligente ; c'est le compilateur qui effectue une comptabilité en temps réel des échecs potentiels.

Pour prouver cela, nous réduisons le délai d'attente à seulement 50 millisecondes. L'exécution du code produit alors une TimeoutError, exactement comme le système de typage l'avait prédit. Cette boucle de rétroaction au moment de la compilation, vérifiée à l'exécution, est une fonctionnalité puissante d'Effect: Production-Grade TypeScript et de son approche visant à rendre les échecs visibles et gérables.

Cet article vous plaît ? Recevez-en un comme celui-ci chaque matin.

un e-mail par jour · désinscription en deux clics · aucun traqueur tiers

Le bénéfice — et le coût du changement

Le suivi explicite des erreurs et des dépendances brille dans les services critiques comme l'authentification et les paiements. Dans ces domaines, les chemins de rejet cachés — tels qu'une expiration de délai d'une API externe ou une perte de connexion à la base de données — rendent la récupération et l'examen beaucoup plus difficiles. L'approche basée sur le typage d'Effect garantit que vous traitez ces modes de défaillance potentiels de manière proactive, et non réactive.

Effect offre bien plus qu'un type Result basique. Il inclut un moteur d'exécution robuste qui fournit des outils pour les retries, les timeouts, la concurrence et la gestion des dépendances dès la sortie de boîte. Au lieu de remplacer instantanément votre code basé sur les Promise, Effect peut le compléter, permettant une adoption et une intégration progressives dans des parties spécifiques et à haute valeur ajoutée de votre application.

L'adoption d'Effect nécessite un investissement en apprentissage. Le modèle, avec sa signature distincte Effect<A, E, R>, prend du temps à assimiler, en particulier la façon dont les types d'erreurs évoluent dans votre pipeline. Comme les types Effect se propagent naturellement à travers les frontières de l'application, les équipes doivent soigneusement peser ces coûts d'apprentissage et de migration par rapport aux avantages d'une fiabilité et d'une observabilité accrues, en particulier pour les systèmes sensibles.

Questions fréquemment posées

Qu'est-ce qu'Effect dans TypeScript ?

Effect est une bibliothèque pour modéliser des programmes asynchrones avec des valeurs de succès explicites, des erreurs typées et des services requis.

En quoi Effect est-il différent d'une Promise ?

Une Promise décrit une valeur qui peut être résolue ou rejetée, mais n'encode pas les types de rejet. Effect modélise également les échecs typés et les dépendances.

Comment les types Effect changent-ils lorsqu'une erreur est gérée ?

La gestion d'une erreur typée supprime cet échec du type d'erreur de l'Effect ; l'ajout d'une opération telle qu'un timeout peut ajouter un nouvel échec typé.

Chaque projet TypeScript devrait-il adopter Effect ?

Pas nécessairement. Cela peut aider les systèmes complexes qui nécessitent des échecs explicites et des contrôles à l'exécution, mais ses concepts et son empreinte de typage nécessitent un investissement d'adoption.

Found this useful? Share it.

For builders

Want Stork to write one of these about your product?

Send us a URL. We use the product, form a view, and publish what we actually think — in 8 languages, labeled Sponsored, with no copy approval on your side. That last part is what makes it worth quoting.

See how it works$199 · AI tools & software only

Pour les builders

Cette page travaille pour l’outil de quelqu’un d’autre.

Les agents IA la lisent. Des acheteurs y arrivent. Elle répond en huit langues et via MCP. Votre outil peut avoir la sienne — en ligne en 24 heures.