如何检查Typescript中的类型相等性?[副本]

zazmityj  于 2023-05-01  发布在  TypeScript
关注(0)|答案(1)|浏览(246)

此问题已在此处有答案

How to test if two types are exactly the same(7个回答)
3天前关闭。

  • 在搜索如何在TypeScript中测试类型相等时,我发现了这个SO question,它的标题看起来很有前途,但它的实际问题不是关于类型相等的测试。*

我想要的东西,可以测试两种类型的等效性:

type IsEqual<Type1, Type2> = ???;

例如,它可以用来确定重载函数的返回类型:

type IsAmbiguous<T> = T extends { isString: infer K } ? IsEqual<K,boolean> extends true ? T : never : never;

function doThing(val: number,    opts: { isString: true }): string;
function doThing(val: number,    opts: { isString: false }): number;
function doThing<T>(val: number, opts: IsAmbiguous<T>): string | number;

前两个重载函数根据传入选项的窄类型预测返回类型。然而,在第三重载函数中,opts可以通过变量传递,在这种情况下,isString的类型是布尔型的,并且返回类型将在运行时由doThing实现确定,但在编译时不能(或可能不)被TypeScript编译器知道。
IsEqual的执行情况如何?

ryevplcw

ryevplcw1#

回答我自己的问题。

type IsEqual<Type1,Type2> = (Type1 | Type2) extends (Type1 & Type2) ? true : never;

测试类型相等的关键是使用交集(&)和并集(|)运算符。我们测试两个类型的联合是否扩展了两个类型的交集。在TypeScript(和JavaScript)中,subtype extends supertype意味着subtype是更具体的类型,supertype是更一般的类型。对于对象和类,这通常意味着向派生类型添加属性或方法。对于标量类型,这意味着子类型是一个特定的值(3.14 extends number)。
在这里,IsEqual采用更通用的类型(union),并测试它是否扩展了更窄的类型(intersection)。如果它确实扩展了,那么这两个类型必须相等,因为任何一个类型都没有添加任何额外的内容。如果引入了一些额外的类型,则超类型将比子类型更窄,因此无法扩展。
下面是一些狭义和广义延伸的例子。

var goo: string | number extends string ? true : false                  = false;
var boo: true extends boolean ? true : false                            = true;
var too: { x: number } extends { x: number, y: number } ? true : false  = false;
var woo: { x: number, y: number } extends { x: number } ? true : false  = true;

下面是一个包含IsEqual实现的TS Playground及其使用示例。
在准备这个Q&A时,我发现this medium articlethis SO answer非常有帮助。

相关问题