【问题标题】:How can I reference to a type which is part of a union type, in TypeScript?如何在 TypeScript 中引用属于联合类型的类型?
【发布时间】:2020-10-14 00:20:47
【问题描述】:

我在 TypeScript 中为动作定义了联合类型:

type Action = {
  type: 'reset',
} | {
  type: 'add',
  payload: number
} | {
  type: 'minus',
  payload: number
}

在某些函数中,我想引用联合类型的一部分,比如:

function handleAdd(state: State, action: {
  type: 'add',
  payload: number
}): State => {
  // handle the add
}

有没有办法简化action的输入所以我不需要重复完整的定义

{
  type: 'add',
  payload: number
}

这里?

更新:

我不想单独预定义每个动作类型。有没有其他解决方案,比如Action[type='add']

【问题讨论】:

标签: typescript typescript-typings


【解决方案1】:

这可以依靠distributive conditional types来实现:

type ExtractType<T extends Action['type'], A = Action> =
    A extends { type: T } ? A : never;

type Add = ExtractType<'add'>; // { type: 'add'; payload: number; }

Playground

分布式条件类型在实例化期间自动分布在联合类型上。例如,T extends U ? X : Y 的实例化具有 A | B | C 的类型参数 T 被解析为 (A extends U ? X : Y) | (B extends U ? X : Y) | (C extends U ? X : Y)

【讨论】:

    【解决方案2】:

    创建一个缩小联合的类型:

    type TypedAction<T extends Action['type']> = Extract<Action, {type: T}>
    

    然后使用like:

    (action: TypedAction<"add">)
    

    Playground Link

    【讨论】:

    • 请注意,当type 在初始类型中定义为type? 时,您还必须在Extract&lt;&gt; 位中添加?
    【解决方案3】:

    将联盟的分支反应出来,所以

    type Add = {
      type: 'add',
      payload: number
    };
    ...
    type Action = Add | ...;
    ...
    

    【讨论】:

    • 这是一种可能的解决方案,我想知道是否有其他方法可以不单独预定义每种类型
    猜你喜欢
    • 1970-01-01
    • 2023-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-26
    • 1970-01-01
    • 2019-02-13
    • 1970-01-01
    相关资源
    最近更新 更多