🔎 搜索词
通用类型变量交集并集顺序
🕗 版本与回归信息
- 这是我尝试的每个版本的行为,我查阅了关于泛型的常见问题解答
⏯ Playground链接
工作台复现
💻 代码
type Union<A, B> = A | B
type UnionAny<T> = Union<T, any>
type UnionUnknown<T> = Union<unknown, T>
// these should all be the same type but are respectively: any, any, unknown
type UA0 = Union<unknown, any>
// ^?
type UA1 = UnionAny<unknown>
// ^?
type UA2 = UnionUnknown<any>
// ^?
type Intersect<A, B> = A & B
type IntersectAny<T> = Intersect<T, any>
type IntersectNever<T> = Intersect<never, T>
// these should all be the same type but are respectively: never, any, never
type AN0 = Intersect<never, any>
// ^?
type AN1 = IntersectAny<never>
// ^?
type AN2 = IntersectNever<any>
// ^?
🙁 实际行为
类型 UA0
, UA1
分别解析为 any
和 UA2
解析为 unknown
。它们都Map到相同的 unknown
和 any
的联合类型,所以应该是相同的类型。
类型 AN0
, AN2
分别解析为 never
和 AN1
解析为 any
。它们都Map到 any
和 never
的交集类型,所以应该是相同的类型。
🙂 预期行为
我期望 UA0
, UA1
和 UA2
能够解析为相同的类型(可能是 any
,但最好是 unknown
)
我期望 AN0
, AN1
和 AN2
能够解析为相同的类型(可能是 never
)
关于问题的附加信息
- 无响应*
7条答案
按热度按时间daupos2t1#
它只在左侧是类型参数时才分配。
具体来说,一个裸类型参数。像
(T & U) extends ...
这样的东西也不是分配的。噢。你是对的。我无法确定这是 bug 还是特性。
例如,
T|T
的行为类似于裸类型参数T
,但T|U
并不这样,即使当T
和U
用相同的类型示例化时也是如此!还有一个奇怪的情况是,即使 LHS 不包含类型参数,当 LHS 是
any
但 RHS 不是时,条件表达式会计算出两个分支的并集。pkbketx92#
还有一种奇怪的情况,即使左侧不包含类型参数,当左侧是除右侧之外的任何值时,条件表达式的结果为两个分支的并集。
是的,这是与分布分开的行为,是有意图的。
sq1bmfud3#
还有一个有趣的情况是,即使左侧不包含类型参数,当左侧是除右侧之外的任何值时,条件表达式的结果为两个分支的并集。
是的,这是与分布分开的行为,并且是有意为之的。
是的,这是有意为之的。原因(
any
是union
的上界,所以我们应该推断出尽可能通用的类型)似乎暗示unknown extends T ? A : B
应该计算为A | B
。liwlm1x94#
问题可能是
unknown
被假定为|
和any
的吸收元素,而&
被假定为一个吸收元素。我认为包含类型参数的类型表达式应该只依赖于这些类型参数的最终值是合理的。yzuktlbb5#
一般来说,联合和交集类型的操作符都是可交换的(函数交集除外,它们被视为重载,并且是顺序相关的),任何包含
any
的联合/交集都应该始终简化为any
。lokaqttq6#
@fatcerberus 抓住了关键点。
包含任何的联合/交集总是应该简化为任何。
我认为以下两种情况在逻辑上都是一致的:
any | unknown
和any & never
都是any
,因为any
代表了类型系统的幂等性。T | unknown
是unknown
,T & never
是never
,因为unknown
和never
限制了类型层次结构,而any
不包含关于限定值的信息。为什么前者应该被覆盖?我找不到明确说明这一点的文档,但这感觉是一个重要的设计选择。
编辑:我可以看到意图是在 #24439 中让
unknown & any
和unknown | any
都成为any
。但是那里记录的行为与当前行为不同,即:这似乎比当前行为(在这种情况下,这种类型评估为
never
)更一致。再次编辑:我对分配条件的理解是错误的。它只在左侧是类型参数时分配。
2izufjch7#
它仅在左侧为类型参数时才分配。
具体来说,一个裸露的类型参数。像
(T & U) extends ...
或类似的东西也不是可分配的。这就是为什么你可以写[T] extends [U] ? ...
以防止分配的原因。