如何在TypeScript中引用联合类型中的类型?

5

我在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']


将联合部分定义为单独的类型或接口有什么问题? - Николай Гольцев
@НиколайГольцев 只是想探索更多的可能性。 - Freewind
可能是TypeScript鉴别联合类型的实用程序类型的重复问题。 - ford04
3个回答

6
这可以通过依赖分布式条件类型来实现:
type ExtractType<T extends Action['type'], A = Action> =
    A extends { type: T } ? A : never;

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

游乐场

分配式条件类型在实例化期间会自动分配到联合类型上。例如,对于类型参数 T,使用类型参数 A | B | C 实例化 T extends U ? X : Y,将被解析为 (A extends U ? X : Y) | (B extends U ? X : Y) | (C extends U ? X : Y)

3

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

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

然后像这样使用:

(action: TypedAction<"add">)

Playground Link


1
请注意,当初始类型中定义为 type? 时,您还必须在 Extract<> 中添加 ? - Jorrit Schippers

1
将联盟的分支重新整理,因此。
type Add = {
  type: 'add',
  payload: number
};
...
type Action = Add | ...;
...

这是一种可能的解决方案,我想知道是否有其他方法不需要预先单独定义每种类型。 - Freewind

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接