Home > Mobile >  When passing a union type argument to a function, how do I type the receiving function's argume
When passing a union type argument to a function, how do I type the receiving function's argume

Time:08-04

Let's say I have a union type as follows:

type State = {
  value: number
  things: []
}

type Action =
  | {
      type: 'INCREMENT'
      data: number
    }
  | {
      type: 'DECREMENT'
      data: number
    }
  | {
      type: 'DO_THING'
      data: {
        id: string
        name: string
      }
    }

And a reducer function like so:

function reducer(state: State, action: Action): State {
  switch (action.type) {
    case 'INCREMENT':
      return increment(state, action)
    case 'DECREMENT':
      return decrement(state, action)
    case 'DO_THING':
      return addItem(state, action)
    default:
      return state
  }
}

When typing my little action helper functions, I'm greeted with an error. Example:

function increment(state: State, action: action): State {
  return {
    ...state,
    number: action.data   1 // this is the culprit
  }
}

Basically, because of the union type for which data is either number or the object defined, I'm getting an error like so:

Type 'number | { id: string; value: string }' is not assignable to type 'number'

I get why the error is here, because value is indeed strongly typed as just number. But… how do I solve this? How do I correctly type things to make it all play nice?

CodePudding user response:

You can use the Extract utility to pull out the Increment action by its type.

function increment(state: State, action: Extract<Action, { type: 'INCREMENT' }>): State {
  return {
    ...state,
    value: action.data   1,
  };
}
  • Related