TypeScript中函数定义中的嵌套泛型

War*_*ock 9 typescript

我正在尝试依靠动作类型为redux动作制作类型安全的处理程序.例如,任何操作都可以描述为:

type ActionType<T extends string> = {
  type: T
};
Run Code Online (Sandbox Code Playgroud)

对于特定的行动,人们可以:

type MyAction = ActionType<'hey' | 'there'>;
Run Code Online (Sandbox Code Playgroud)

现在,我想限制一个处理函数,只允许'hey'或'there'作为一个类型.最后我希望这样的事情:

handleAction<MyAction>('hey');
Run Code Online (Sandbox Code Playgroud)

处理函数的定义可以是:

function handleAction<A extends ActionType<T>>(type: T){
...
}
Run Code Online (Sandbox Code Playgroud)

但我有一个打字稿编译器错误:


TS2304:找不到名称'T'.


所以,我必须以这种方式修改这个处理函数定义:

function handleAction<A extends ActionType<T>, T extends string>(type: T){
...
}
Run Code Online (Sandbox Code Playgroud)

它有效,但看起来很难看:

handleAction<MyAction, 'hey' | 'there'>('hey');
Run Code Online (Sandbox Code Playgroud)

TS游乐场

有什么更好的方法来处理这个问题?

Tit*_*mir 10

编辑

您可以使用类型查询来获取类型type

function handleAction<A extends ActionType<string>>(type: A ['type']) {
}

handleAction<MyAction>('hey');
Run Code Online (Sandbox Code Playgroud)

或者您可以使用 2.8 中的条件类型从中提取泛型参数ActionType(2.8 在撰写本文时尚未发布,但将在 2018 年 3 月发布,您可以通过 获取npm install -g typescript@next

type ActionType<T extends string> = {
  type: T
};

type MyAction = ActionType<'hey' | 'there'>;


function handleAction<A extends ActionType<string>>(type: A extends ActionType<infer U> ? U : never) {
}

handleAction<MyAction>('hey');
Run Code Online (Sandbox Code Playgroud)

该解决方案基于条件类型推理行为ActionType<infer U>基本上说:如果ActionType其他类型的扩展U给我类型U。因此,U将任何字符串文本类型传递给ActionType我们的情况。然后我们U在条件类型的真分支上使用,这成为输出条件类型的最终类型。在这种情况下,我们不关心 false 分支,所以我们使用 never。