我已经编写了自己的内置实用程序类型InstanceType
:的实现
type MyInstanceType<C extends abstract new (...args: any) => any>
= C extends abstract new (...args: any) => infer R ? R : never
它与实际实现方式非常接近:
type BuiltInInstanceType<C extends abstract new (...args: any) => any>
= C extends abstract new (...args: any) => infer R ? R : any
唯一的区别是我有最后一个词never
,而实际实现有any
这导致了它对待any
:的方式不同
type MyWithAny = MyInstanceType<any> // unknown
type BuiltInWithAny = BuiltInInstanceType<any> // any
我认为这意味着它以某种方式进入了条件类型的虚假分支
所以问题是,这怎么可能呢?考虑到条件类型与类型约束相同,因此任何对条件类型错误的东西也应该对类型约束错误,因此应该导致类型约束失败错误
第二个问题,为什么MyWithAny
正是unknown
,而不是例如never
?
UPD:根据答案和讨论,以下是评估方式(接受的答案中有更多详细信息(:
- 在计算
MyWithAny
和BuiltInWithAny
时,使用any
作为泛型函数的参数已完全禁用类型约束。所以MyInstanceType
的评估就像
type MyInstanceType<C> = C extends abstract new (...args: any) => infer R ? R : never
并且CCD_ 12已经像一样被评估
type BuiltInInstanceType<C> = C extends abstract new (...args: any) => infer R ? R : any
使虚假分支成为可能的
- 如果TS无法计算条件类型的分支,则会将其计算为两个分支的并集类型。因此,由于
any
包括可能满足或可能不满足条件类型的实例,因此MyWithAny
的类型将变为R | never
,BuiltInWithAny
的类型将变成R | any
- 在TS不能解析
R
的情况下,它认为是unknown
。因此,MyWithAny
的结果类型是unknown | never
即unkonown
,而BuiltInWithAny
的结果类型则是unknown | any
即any
您的示例可以简化为smth,如下所示:
type WithNever = <T>(t: T) => T | never
type WithAny = <T>(t: T) => T | any
type NeverRetutn = ReturnType<WithNever>
type AnyRetutn = ReturnType<WithAny>
我们对T | never
和T | any
感兴趣。
若TypeScript无法推断T
的类型,TS将分配unknown
类型。
参见示例:
type ReturnUnknown = ReturnType< <T>(t: T) => T> // unknown
什么是never
?(文档(
never类型是每种类型的子类型,可分配给每种类型
实际上,应该将never
视为空并集。
type Check = 1 | never // 1
type Check2 = unknown | never // unknown
type Check3 = any | never // any
正如您可能已经注意到的,never
被分配给每种类型。
让我们回到你的问题上来。事实上,您正在接收类型的并集。
type MyWithAny = MyInstanceType<any> // R | never
type BuiltInWithAny = BuiltInInstanceType<any> // R | any
我希望,现在已经清楚了,R | never
将被解析为unknown
,因为R
是未知的,而never
是可分配给未知的。
R | any
与unknown | any
相同,因为任何类型都可以分配给any
,所以只得到any
。
但你为什么要接受类型的联合?很明显,条件类型应该返回true或false分支,但不能同时返回两者。这不是它在TS中的工作方式。
因为您提供了any
作为参数,所以应用了每个分支。我认为这是意料之中的事,因为我没有足够的论据来说明应该只应用真分支,或者只应用假分支。
考虑到条件类型与类型约束相同,因此任何对条件类型错误的东西也应该对类型约束错误,因此应该导致类型约束失败错误
既然any
类型实际上是任何类型(每种类型(,为什么您认为应该应用false
分支?请记住,您使用的是类型,而不是值。
我对falsy分支感到困惑的是,我如何理解它,无论我们在上放什么,它都应该被疏散到永远
它不能总是评估为false分支。这种假设是不正确的。
考虑下一个例子:
type CheckAny = any extends abstract new (...args: any) => any ? true : false
上述条件评估为true | false
。而true | false
并集只是一个内置的boolean
类型。
我认为打字不够聪明。TS只是告诉您any
类型可以扩展构造函数类型,但同时它不能扩展。