如何检查类型是否相同?

时间:2019-10-25 18:16:17

标签: typescript generics

我要检查2种类型是否相同。我期望

export type AreSame<T, U, R> = T extends U ? U extends T ? R : never : never;

可以正常工作,但实际上fails在工会上使用:

type A = AreSame<1, 1, Object>          // Object
type B = AreSame<1, 2, Object>          // never
type C = AreSame<1, number, Object>     // never
type D = AreSame<1, 1 | 2, Object>      // Object - why???
type E = AreSame<1 | 2, 1 | 3, Object>  // Object - why???
type F = AreSame<1 | 2, 1 | 2, Object>  // Object

我该如何解决?

2 个答案:

答案 0 :(得分:2)

我只是在这里猜测,但是如果我们认为联合类似于逻辑或,那将是有道理的。

让我尝试对问题采取的步骤进行伪编码。

1 extends (1|2) ? (1|2) extends 1 ? Object : never : never // becomes ->
(1 extends 1 || 1 extends 2) ? (1 extends 1 || 2 extends 1) ? : Object : never : never

我会考虑检查打字稿代码以检查其工作原理。

编辑:为解决此问题,我在打字稿存储库中找到了this github issue

最好的解决方案是:

export type Equals<X, Y> =
    (<T>() => T extends X ? 1 : 2) extends
    (<T>() => T extends Y ? 1 : 2) ? true : false;

也许您可以根据自己的情况进行调整?希望能有所帮助:)

答案 1 :(得分:2)

您的条件类型偶然是distributive。这意味着它最终会分解并集,评估每个成员的类型,然后将它们并集在一起。请熟悉该文档,因为它很重要。如果您有一个类似type G<T> = T extends U ? X : Y的类型,其中T是一个“裸”类型参数(因此它是T extends而不是SomethingWith<T> extends),那么它将分布。有时这就是您想要的。现在不是。

关闭分配条件类型的最简单方法是“覆盖”裸类型参数:将T extends U ? X : Y变成[T] extends [U] ? X : Y。所以:

export type AreSame<T, U, R> = [T] extends [U] ? [U] extends [T] ? R : never : never;

type A = AreSame<1, 1, Object>          // Object
type B = AreSame<1, 2, Object>          // never
type C = AreSame<1, number, Object>     // never
type D = AreSame<1, 1 | 2, Object>      // never
type E = AreSame<1 | 2, 1 | 3, Object>  // never
type F = AreSame<1 | 2, 1 | 2, Object>  // Object

好的,希望能有所帮助;祝你好运!

Link to code

相关问题