当前位置: 首页 > 知识库问答 >
问题:

带区分并集的Typescript条件类型

钱远
2023-03-14

我使用的库定义了以下类型:

type VoidableCallback<EventValue> = EventValue extends void ? () => void : (val: EventValue) => void;

库公开了一个返回上述类型的函数:

declare function fn<T>(): VoidableCallback<T>;

我想将此函数用于有差别的联合:

type Action = { type: 'add'; n: number } | { type: 'multiply'; n: number };

const callback = fn<Action>();
callback({ type: 'add', n: 1 });

但是TypeScript(3.4.1)给了我这个错误信息:

类型“add”不可分配给类型“add”

预期的类型来自属性'type',该属性在这里声明为类型{type:“add”;n:number;}

我不明白为什么会这样-似乎总和(并集)类型被解释为“乘积”类型。

如果将类型定义更改为:

type VoidableCallback<EventValue> = (val: EventValue) => void;

... Typescript没有抱怨。这与条件类型和联合类型有关。

如果能理解这里发生了什么,那么也许我可以做一个公共关系到图书馆(rxjs-钩子)。

共有1个答案

庞鸿骞
2023-03-14

这是由条件类型的分布行为造成的。条件类型分布在裸类型参数上。这意味着,如果type参数包含联合,则条件类型将应用于联合的每个成员,结果将是所有应用程序的联合。因此,在您的情况下,我们将得到VoidableCallback

关于交集出现错误的原因是typescript处理函数签名联合的方式,它基本上要求参数与联合中的所有签名兼容,因此参数必须是所有可能参数类型的交集。你可以在这里读到

简单的解决方案是禁用条件类型的分发。这可以通过将类型参数放置在元组中轻松完成:

type VoidableCallback<EventValue> = [EventValue] extends [void] ? () => void : (val: EventValue) => void;
type Action = { type: 'add'; n: number } | { type: 'multiply'; n: number };
declare function fn<T>(): VoidableCallback<T>;
const callback = fn<Action>();
callback({ type: 'add', n: 1 }); //ok now

游乐场链接

 类似资料:
  • 本节介绍 TypeScript 高级类型中的条件类型(conditional type),条件类型就是在初始状态并不直接确定具体类型,而是通过一定的类型运算得到最终的变量类型。 1. 慕课解释 条件类型用来表达非均匀类型映射,可以根据一个条件表达式来进行类型检测,从两个类型中选出其中一个: T extends U ? X : Y 语义类似三目运算符:若 T 是 U 的子类型,则类型为 X,否则类

  • 在一个个人项目中,我遇到了一个TypeScript条件类型的问题。我对TypeScript文档中的条件类型有基本的了解。我希望下面的设置工作,但它给出了一个类型错误。 基本上,我试图为从磁盘加载的树节点定义一个接口。这意味着,由于缺少文件等原因,某些节点可能无法正确加载。因此,任何节点实现都可能包含或。 我希望方法的实现可以返回,因为接口是通过类型扩展

  • 问题内容: 我的Angular代码有什么问题?我正进入(状态: 的HTML 问题答案: Angular版本2,…,9提供了几种有条件地添加类的方法: 第一类 第二类 和多个选项: 第三类 四类

  • 我的角码出了什么问题?我得到以下错误: 无法读取BrowserDomAdapter.RemoveClass中未定义的属性“Remove”

  • 本文向大家介绍集的分区,包括了集的分区的使用技巧和注意事项,需要的朋友参考一下 集合的分区(例如S)是满足以下三个条件的n个不相交的子集(例如P 1,P 1,... P n)的集合- P i不包含空集。 对于所有0 <i≤n,                        [P i ≠{∅} 子集的并集必须等于整个原始集合。                        [P 1 ∪P 2 ∪..

  • 我想基于泛型值返回不同的类型。例如: 但我有一个错误: 类型字符串[]不能分配给类型T扩展Base?String[]:字符串