4 votes

Inférer les types d'union des gardes de type en TypeScript

TypeScript semble avoir des problèmes pour inférer les types d'union des gardes de type. Par exemple, considérez une fonction pour combiner un tableau de gardes de type avec la signature suivante

function combine(guards: ((x: any) => x is T)[]): (x: any) => x is T

et considérez les gardes de type suivants avec A et B ayant des propriétés différentes

function isA(x: any): x is A
function isB(x: any): x is B

Maintenant, je m'attendrais à ce que combine([isA, isB]) fonctionne et ait le type inféré (x: any) => x is A | B mais au lieu de cela, j'obtiens une erreur disant qu'un argument de type ((x: any) => x is A | (x: any) => x is B)[] n'est pas assignable au paramètre de type (x: any) => x is A, ce qui signifie que T est inféré comme A plutôt que A | B.

En spécifiant explicitement T, c'est-à-dire combine([isA, isB]), cela fonctionne comme prévu. Existe-t-il un moyen de modifier la signature de combine de manière à ce que cela puisse être inféré?

0 votes

Vous pouvez toujours utiliser function combine2(guards: [((x: any) => x is T), ((x: any) => x is U)]): (x: any) => x is T | U, mais je suppose que vous voulez accepter un tableau avec un nombre variable d'éléments?

1 votes

Exactement, je cherche une solution qui fonctionne avec n'importe quel (nombre positif) d'éléments de tableau.

7voto

devilmaster Points 439

Vous pouvez utiliser un paramètre de type pour désigner la fonction entière au lieu de simplement le type protégé. Cela permet au compilateur d'inférer une union de fonctions de garde. Nous pouvons ensuite utiliser un type conditionnel pour extraire l'union des types protégés :

type GuardType = T extends (o: any) => o is infer U ? U : never

class A { q: any }
class B { p: any }
declare function isA(x: any): x is A
declare function isB(x: any): x is B

declare function combine x is any)>(guards: T[]): (x: any) => x is GuardType

let isAB = combine([isA, isB]); // (x:any) => x is A|B

0 votes

J'ai essayé de résoudre ce problème depuis assez longtemps, tu viens de me sauver <3 Peut-être pourrais-tu aider cette personne aussi stackoverflow.com/questions/52236191/… J'ai soumis une réponse mais c'est plutôt bricolé et j'aimerais savoir s'il existe une meilleure solution.

0 votes

@ClémentPrévost J'ai vu ta réponse, c'était moi qui l'a likée :)

1 votes

C'est incroyable. Je me demandais comment faire cela avec un type d'intersection, pour y parvenir: let isAB = combine([isA, isB]); // (x:any) => x is A & B

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X