繁体   English   中英

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

[英]Nested Generics in function definition in TypeScript

我正在尝试为依赖于操作类型的redux操作创建类型安全的处理程序。 例如,任何动作都可以描述为:

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

对于特定的动作,可以有:

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

现在,我想将处理程序函数限制为仅允许“ hey”或“ there”作为类型。 最后,我期望这样的事情:

handleAction<MyAction>('hey');

处理程序函数的定义可以是:

function handleAction<A extends ActionType<T>>(type: T){
...
}

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


TS2304:找不到名称“ T”。


因此,我必须以这种方式修改此处理程序函数定义:

function handleAction<A extends ActionType<T>, T extends string>(type: T){
...
}

它可以工作,但是看起来真的很丑:

handleAction<MyAction, 'hey' | 'there'>('hey');

TS游乐场

有什么更好的方法来解决这个问题?

编辑

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

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

handleAction<MyAction>('hey');

或者,您可以在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');

该解决方案基于条件类型推断行为 ActionType<infer U>基本上说:如果扩展了其他类型U ActionType ,则给我类型U 因此,在本例中, U将是传递给ActionType任何字符串文字类型。 然后,我们在条件类型的真实分支上使用U ,这成为out条件类型的最终类型。 在这种情况下,我们不在乎虚假分支,因此我们从不使用。

有两种方法:

  1. 使用字符串并集。

我喜欢这个,因为它比较简单(针对您描述的问题):

type FileAction = 'save' | 'read' | 'copy';
function doAction (a) {
}
declare function doAction<A extends string> (action: A): void;

doAction<FileAction>('save'); // good, as desired
doAction<FileAction>('xxx'); // error, as expected
  1. 通过括号符号获取.type

这看起来更骇人听闻,但它是一种有效的语法..它不需要您更改对象的形状。

type FileFile <T extends string> = {
  type: T;
}
type WordFile = FileFile<'why'|'you'|'no'|'work'>;

function doAction2 (a) {
}
declare function doAction2<F extends FileFile<string>> (action: F["type"]): void;

doAction2<WordFile>('no'); // good, as desired 
doAction2<WordFile>('xxx'); // error, as expected

这可以清理一些东西,但是我不确定这是否是您想要的:

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

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

function handleAction<A extends ActionType<T>, T extends string>(type: T){
}

handleAction<MyAction, MyWord>('hey');

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM