Utilisation du type union avec générique

Oct 27 2020

J'ai une fonction qui accepte un paramètre qui est un objet composé d'un champ (chaîne) et d'arguments (objet littéral).

Je voudrais que la vérification du type d'arguments soit validée en fonction de la nature du champ. Je souhaite également faire une définition qui peut être étendue partout où j'en ai besoin (d'où le générique).

Définition:

 export interface EventDefinition<
    TField extends string,
    TArgs extends any
  > {
    field: TField
    arguments: TArgs
  }

Ma fonction:


export const myFn =  (
  params:
    | EventDefinition<
        'actionOne',
        {
          id: string
        }
      >
    | EventDefinition<
        'actionTwo',
        {
          emailAddress: string
        }
      >
) => {
  const { args, field } = params

  switch(field) {
    case 'actionOne':
      console.log(args.id)
      break;
      case 'actionTwo':
      console.log(args.emailAddress)
      break;
  }
}

Alors que la propriété field valide, les arguments ne le font pas et entraînent des erreurs (par exemple avec args.id):

Property 'id' does not exist on type '{ id: string }'.
Property 'id' does not exist on type '{ emailAddress: string; }'.

Comment définir correctement cela?

Réponses

3 TitianCernicova-Dragomir Oct 27 2020 at 03:38

Typescript ne gardera pas une variable basée sur une autre, ce n'est tout simplement pas pris en charge.

Si vous utilisez l'argument lui-même, l'analyse du flux de contrôle peut déterminer les types de manière appropriée

  switch(params.field) {
    case 'actionOne':
      console.log(params.arguments.id)
      break;
      case 'actionTwo':
      console.log(params.arguments.emailAddress)
      break;
  }

Lien Playground