0

I am using Typescript, I am wondering if it is possible to define what combination can be put into the function. I have following code (very simplified):

interface actionType {
    type: string,
    payload: {
        count?: number,
        first?: number,
        second?: number,
        name?: string,
        message?: string
    }
}

const ADD_ONE = 'addOne'
const MULTIPLY = 'multiply'
const ADD_TOGETHER = 'addTogether',

const theFuntion = (action: actionType) => {
  switch (action.type) {
    case "AddOne": {
      const { count } = action.payload
      const result: number = count + 1
      return result;
    };
    case "Multiply": {
      const { first, second } = action.payload
      const result: number = first * second
      return result;
    };
    case "AddTogether": {
      const { name, message } = action.payload
      const result: string = name + message
      return result;
    };
  }
}

Following works:

theFuntion({ type: ADD_ONE, payload: { count: 9 } }) // works
theFuntion({ type: MULTIPLY, payload: { first: 3, second: 5 } }) // works
theFuntion({ type: ADD_TOGETHER, payload: { name: 'Peter', message: 'Hello Wolrd!' } }) // works

These will and should not work, but does not show type error's:

theFuntion({ type: MULTIPLY, payload: { count: 9 } })
theFuntion({ type: ADD_TOGETHER, payload: { first: 3, second: 5 } })
theFuntion({ type: ADD_ONE, payload: { name: 'Peter', message: 'Hello Wolrd!' } })

So my question is if there is a way to define an interface or something else to show me if I make a combination error when coding.


SOLUTION:

(Credits: @matthieu-riegler)

type ActionType = 'AddOne' | 'Multiply' | 'AddTogether'

type AddOne = { type: 'AddOne', payload: { count: number } }
type Multiply = { type: 'Multiply', payload: { first: number, second: number } }
type AddTogether = { type: 'AddTogether', payload: { name: string, message: string } }

type Action = AddOne | Multiply | AddTogether;

const theFuntion = (action: Action) => {
  ...
}
aronmal
  • 15
  • 1
  • 7

1 Answers1

1

You'll need a discriminated union for that !

type ActionType = 'AddOne' | 'Multiply' | 'AddTogether'

type AddOne = { type: 'AddOne', payload: { count: number } }
type Multiply = { type: 'Multiply', payload: { first: number, second: number } }
type AddTogether = { type: 'AddTogether', payload: { nameOfPerson: string, message: string } }

type Action = AddOne | Multiply | AddTogether;

const theFuntion = (action: Action) => {
  switch (action.type) {
    case "AddOne": {
      const result: number = action.payload.count + 1
      return result;
    };
    case "Multiply": {
      const result: number = action.payload.first * action.payload.second
      return result;
    };
    case "AddTogether": {
      const result: string = action.payload.nameOfPerson + action.payload.message
      return result;
    };
  }
}

theFuntion({ type: "AddOne", payload: { count: 9 } }) // works

theFuntion({ type: "Multiply", payload: { first: 3, second: 5 } }) // works

theFuntion({ type: "AddTogether", payload: { nameOfPerson: 'Peter', message: 'Hello Wolrd!' } }) // works


// These show an error 

theFuntion({ type: "Multiply", payload: { count: 9 } })

theFuntion({ type: "AddTogether", payload: { first: 3, second: 5 } })

theFuntion({ type: "AddOne", payload: { nameOfPerson: 'Peter', message: 'Hello Wolrd!' } })

Playground

Matthieu Riegler
  • 31,918
  • 20
  • 95
  • 134