首页 > 解决方案 > Using union type with generic

问题描述

I have a function that accepts a parameter which is an object consisting of a field (string) and arguments (object literal).

I'd like the arguments type check to be validated dependent on what the field is. I also wish to make a definition that can be extended wherever I needed (hence the generic).

Definition:

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

My function:


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;
  }
}

While the field property validates the args do not and result in errors (for ex with args.id):

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

How can I correctly define this?

标签: typescript

解决方案


Typescript will not guard one variable based on another, this is just not supported.

If you use the argument itself control flow analysis can determine the types appropriately

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

Playground Link


推荐阅读