如何理解类型 any、unknown、{} 之间以及它们与其他类型之间的关系?

And*_*lev 6 types typescript

试图理解类型之间的关系我有这个代码

type CheckIfExtends<A, B> = A extends B ? true : false;

type T1 = CheckIfExtends<number, unknown>; //true
type T2 = CheckIfExtends<number, {}>; //true
type T3 = CheckIfExtends<number, any>; //true
type T4 = CheckIfExtends<() => void, unknown>; //true
type T5 = CheckIfExtends<() => void, {}>; //true
type T6 = CheckIfExtends<() => void, any>; //true
type T7 = CheckIfExtends<unknown, any>; //true
type T8 = CheckIfExtends<any, unknown>; //true
type T9 = CheckIfExtends<{}, unknown>; //true
type T10 = CheckIfExtends<{}, any>; //true
type T11 = CheckIfExtends<any, {}>; //boolean
type T12 = CheckIfExtends<unknown, {}>; //false
Run Code Online (Sandbox Code Playgroud)

链接到游乐场

有人可以解释一下吗?有什么区别?怎么可能any extends {}同时any不延长{}?如果any extends unknownunknown extends any那么这是否意味着它们是强相等的?它是打字稿对顶部的新漏洞nullundefinded公平问题的JavaScript?

实际上,

type T = CheckIfExtends<any, number>; //boolean
Run Code Online (Sandbox Code Playgroud)

jca*_*alz 7

区别本质上是这样的:

  • any类型故意不合理,因为它可以分配 任何其他类型,也可以任何其他类型分配(可能的例外never,取决于您在何处使用它)。不健全的装置,对于一些类型的基本规则被打破,如传递性子类型。通常,如果A可分配给B并且B可分配给C,则可A分配给C。但any打破了这一点。例如:string可以分配给any,并且any是分配给number......但string就是没有分配给number. 这种特殊的不健全非常有用,因为它允许我们从根本上“关闭”难以或不可能正确键入的代码部分中的类型检查。但是你需要非常仔细地考虑any作为一个类型;它更像是一种“非类型”。

  • 空型,{}是可以像一个对象在运行时被处理(即,一些可以从没有运行时错误读取属性或方法)类型,但它没有公知的在编译时的特性。这并不意味着它没有属性;它只是意味着编译器不知道它们中的任何一个。这意味着只有nullundefined不可分配给{}(null.foo或者undefined.foo是运行时错误)。甚至像这样的原始类型string也可以被视为在运行时具有属性和方法("".length"".toUpperCase()工作,甚至"".foo只是返回undefined)。当然,任何实际的对象类型也将分配给{}.

    另一方面,{}类型不能分配很多类型。如果我{}尝试将type 的值分配给 type 的变量{foo: string},则会出现编译器错误,因为{}不知道包含foo属性。您可以分配{}给自身,或分配给更广泛的类型,例如unknown,或分配给“un-type” any

    这使得{}非常接近 顶级类型,这是所有其他类型都可以分配的类型。它本质上是一个顶部类型,nullundefined从中移除。

  • unknown类型是在 TypeScript 3.0 中引入的,是真正的顶级类型;TypeScript 中的每种类型都可以分配给unknown. Evennullundefined可分配给unknown.

    同样,另一方面,unknown只能分配给它自己和 "un-type" any。即使{}类型不够宽,您也无法分配unknown给它。从概念上讲,您应该能够分配unknown给 union type {} | null | undefined,但故意不实现这一点以保持unknown“真实”顶级类型。


您的大部分CheckIfExtends<A, B>结果都可以通过上述解释。例外是T11

type T11 = CheckIfExtends<any, {}>; //boolean
Run Code Online (Sandbox Code Playgroud)

您的CheckIfExtends<A, B>类型定义是一个分布式条件类型,当A是联合类型时它会做一些有趣的事情,因为如果联合的部分满足两个分支,它允许采用条件的两个分支。它在Ais时也做相同的分布any,除了当Bis anyor 时unknown(所以T8表现正常)。在microsoft/TypeScript#27418中对此有一些讨论。无论如何,T11需要两个分支,你会得到true | false哪个是boolean. (从Microsoft /打字稿#27418,unknownA位置不分发,所以T7T12表现正常以及)。


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