3 votes

problèmes de typographie dans la ville des tuple : préservation des types d'arguments

J'ai du mal à trouver comment faire de mes and ici : elle a un travail simple. elle doit accepter un tas d'éléments, et les concaténer dans un tableau qui commence avec "and"

// the items 'and' may accept
type Item = false
  | {type: "alpha", a: boolean}
  | {type: "bravo", b: number}

// 'and' function adds items to an array
function and<Items extends Item[]>(
    ...items: Items
  ): ["and", ...Items] {

  return ["and", ...items]
}

// calling 'and' with a few items
const [op, item1, item2, item3] = and(
  false,
  {type: "alpha", a: true},
  {type: "bravo", b: 3.14},
)

// verifying the types are preserved
op    //>  type "and"
item1 //>  type Item, expected false
item2 //>  type Item, expected {type: "alpha", a: true}
item3 //>  type Item, expected {type: "bravo", b: 3.14}

le problème est que les éléments 1, 2 et 3 perdent tous leur information de type spécifique d'origine, ce qui fait que mon and est en fait une opération destructive sur les types - à la place, j'ai besoin que les types soient préservés.

existe-t-il une approche différente ? merci !

1voto

Guilhermevrs Points 1200

En effet, le typecript n'est pas très adapté à ce genre d'opérations (pas à ma connaissance, en tout cas).

Le problème semble être qu'il y a des cas où le compilateur ne sera pas en mesure de taper correctement ces types.

const whatsMyType: Item = false

// calling 'and' with a few items
const [op, item1] = and(
  whatsMyType
)

Je choisirais l'une des deux approches suivantes :

Surcharge de travail

Pour : Avoir une frappe correcte sans trop d'efforts

Cons : Pas très évolutif

(obs : c'est l'approche choisie par Tuyau RxJS par exemple)

function and<A extends Item>(a: A): ['and', A];
function and<A extends Item, B extends Item>(a: A, b: B): ['and', A, B];
function and<A extends Item, B extends Item, C extends Item>(a: A, b: B, c: C): ['and', A, B, C];
function and<Items extends Item[]>(
    ...items: Items
  ): ["and", ...Items] {

  return ["and", ...items]
}

Prédicat de type

Pour : Extensible

Cons : Logique supplémentaire dans le code

const isFalseItem = (a: Item): a is false => {return a === false};
const isAlphaItem = (a: Item): a is ({type: "alpha", a: boolean}) => { return !isFalseItem(a) && a.type === 'alpha'}
const isBravoItem = (a: Item): a is ({type: "bravo", b: number}) => { return !isFalseItem(a) && a.type === 'bravo'}

const [op, item1, item2, item3] = and(
  false,
  {type: "alpha", a: true},
  {type: "bravo", b: 3.14},
)

if (isAlphaItem(item1)) {
 // do something alpha
} else if (isBravoItem(item1)) {
 // do something bravo
}

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