如何在打字稿中定义组合?解决方案:歧视联盟

How to define combinations in typescript? Solution: discriminated-union

我正在使用 Typescript,我想知道是否可以定义可以将哪些组合放入函数中。我有以下代码(非常简化):

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

以下作品:

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

这些会而且不应该工作,但不会显示类型错误:

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!' } })

所以我的问题是,如果我在编码时出现组合错误,是否有办法定义一个接口或其他东西来告诉我。


解决方案:

(致谢:@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) => {
  ...
}

为此你需要一个受歧视的工会!

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