类似类型约束和条件类型之间的差异



我已经编写了自己的内置实用程序类型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:根据答案和讨论,以下是评估方式(接受的答案中有更多详细信息(:

  1. 在计算MyWithAnyBuiltInWithAny时,使用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

使虚假分支成为可能的

  1. 如果TS无法计算条件类型的分支,则会将其计算为两个分支的并集类型。因此,由于any包括可能满足或可能不满足条件类型的实例,因此MyWithAny的类型将变为R | neverBuiltInWithAny的类型将变成R | any
  2. 在TS不能解析R的情况下,它认为是unknown。因此,MyWithAny的结果类型是unknown | neverunkonown,而BuiltInWithAny的结果类型则是unknown | anyany

您的示例可以简化为smth,如下所示:

type WithNever = <T>(t: T) => T | never
type WithAny = <T>(t: T) => T | any
type NeverRetutn = ReturnType<WithNever>
type AnyRetutn = ReturnType<WithAny>

我们对T | neverT | 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 | anyunknown | 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类型可以扩展构造函数类型,但同时它不能扩展。

最新更新