typescript - 如何检查类型是否相同?
我想检查这两种类型是否是同一种。我预期
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> // Object - why???
type E = AreSame<1 | 2, 1 | 3, Object> // Object - why???
type F = AreSame<1 | 2, 1 | 2, Object> // Object
我该怎么修复这个?
答案#1
你的条件类型意外地是可分配的。这意味着它最终会拆分联合类型,分别评估每个成员的类型,然后再将它们联合起来。请熟悉相关文档,因为这很重要。如果你有一个类型像 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
好的,希望有帮助;祝你好运!
代码链接
答案#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
我会考虑检查 TypeScript 代码,以了解它到底是如何工作的。
编辑:为了解决这个问题,我在 TypeScript 仓库中找到了这个 GitHub 问题
那里最好的解决方案是这个:
export type Equals<X, Y> =
(<T>() => T extends X ? 1 : 2) extends
(<T>() => T extends Y ? 1 : 2) ? true : false;
也许你可以根据你的情况调整一下?希望有帮助 :)
