一文搞懂 TypeScript 中的 ‘any‘ 和 ‘unknown‘ 类型

​掌握any类型和unknown类型之间的相似性和差异,避免把 TypeScript 当成 AnyScript 来学习。

当你第一次开始使用 TypeScript 时,你是否遇到过很多疯狂的问题,最终你用  any  技巧解决了它们?如果你以后不花时间学习 TypeScript 的类型系统,你可能会发现你把 TypeScript 当成了 AnyScript。

在 TypeScript 中, any  类型被称为顶级类型,所谓顶级类型可以理解为泛型父类型,即可以包含所有值的类型。

在 TypeScript 3.0 中,引入了新的顶级类型 —  unknown  类型,同样,你可以给未知类型的变量赋值。

那么现在问题来了, any  类型和  unknown 类型的区别是什么?any 类型可以理解为我不关心它的类型, unknown 类型可以理解为我不知道它的类型。

事实上,any 类型本质上是类型系统的逃生口,TypeScript允许我们对 any 类型的值执行任何操作,而无需执行任何类型的预先检查。

这有什么问题呢?让我们举个例子:

对于上面的 TypeScript 代码,编译时不会提示任何错误,但是在运行时会抛出运行时错误。作为开发者, any  类型给了我们很多自由,但它也带来了一些陷阱。为了解决  any  类型的安全风险,TypeScript 团队在 3.0 中引入了 unknown 类型,你可以理解为类型安全的  any  类型。

那么, unknown 类型在什么地方体现了类型安全呢?在这里,我们把  callWithErrorHandling  函数参数的类型改为  unknown  类型,然后 TypeScript 编译器会提示相应的错误消息:

相对于 any 类型,TypeScript对 unknown 类型的参数进行类型检查,以避免fn参数不是函数类型,为了解决上述问题,我们需要缩小fn参数的类型范围,即使用 typeof 操作符来确保fn参数是函数类型的对象:

在实践中,你还可以通过 instanceof 或用户定义的类型保护来缩小参数的类型范围:

declare function isFunction(x: unknown): x is Function;function fn(x: unknown) {    if (x instanceof Error) {        x;  // Error    }    if (isFunction(x)) {        x;  // Function    }}

与 any 类型不同,因为TypeScript对 unknown 类型的变量进行类型检查,当我们将上述代码中值变量的类型更改为 unknown 类型时,所有使用该值变量的语句都将失败。

此外,应该注意,unknown 类型的变量只能赋给 any 类型和 unknown 类型本身。
 

我们在之前的文章中已经介绍过 keyof 操作符和 mapped 类型。 any  类型和  unknown  类型在以下情况下表现不同:

type A0 = keyof any;  // string | number | symboltype U1 = keyof unknown;  // nevertype M2<T> = { [P in keyof T]: number };type M21 = M2<any>;  // { [x: string]: number }type M22 = M2<unknown>;  // {}

在上面的代码中,M2 类型被称为映射类型,在映射过程中,如果键类型为  never  类型,则当前键将被过滤掉,因此 M22 类型是一个空对象类型。

在工作中,为了保证类型安全,我们应该尽可能使用 unknown 类型,最后,让我们来看看 unknown 类型在不同类型下进行类型运算的结果:

 any  类型很特殊。当构造或与任何类型组合时,返回的是  any  类型。在阅读完本文后,我相信您已经理解了  any  类型和  unknown  类型之间的区别。您知道如何检测  any  类型和  unknown  类型吗?如果您知道,可以在评论部分提交您的答案。

 欢迎关注公众号:文本魔术,了解更多

  • 12
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 好的。 TypeScript 的 `any` 类型表示一个可以是任何类型的值。它可以用于避免类型检查,或者在你还没有确定类型的情况下使用。但是,使用 `any` 类型会放弃 TypeScript 带来的类型检查的所有优势,因此在能使用更精确类型的地方应尽量避免使用 `any`。 TypeScript 的 `unknown` 类型表示一个未知的类型。它比 `any` 类型更加严格,因为在使用前需要进行类型检查。在某些情况下,你可能希望接收一个未知的值,但是又不想使用 `any` 类型,此时就可以使用 `unknown` 类型TypeScript 的 `never` 类型表示永远不会有返回值的函数的返回值类型。它也可以表示永远不会被执行的代码块的类型。例如,当某个函数的所有可能执行路径都会抛出异常时,它的返回值类型就可以是 `never`。 希望这对你有所帮助。 ### 回答2: TypeScript的`any`、`unknown`和`never`是三种特殊的类型。 1. `any`类型表示任何类型的值都可以赋值给它。它相当于取消了类型检查,可以在编写代码时快速推进开发,但也容易引入潜在的类型错误。使用`any`类型时需要慎重,最好在必要情况下使用,例如在需要与非TypeScript代码进行交互或在临时情况下。 2. `unknown`类型TypeScript 3.0引入的一种类型。与`any`相比,`unknown`类型提供了更加安全的动态类型。当我们不确定变量的类型时,可以使用`unknown`类型来保持类型的不确定性。在使用`unknown`类型的值时,我们必须首先进行类型检查或类型断言,以将其转换为更具体的类型。与`any`不同,`unknown`类型不会自动允许我们执行任意操作。这种类型的引入提高了代码的类型安全性,减少了潜在的类型错误。 3. `never`类型表示它永远不会发生的类型,即表示从不返回值的函数的返回类型以及永远无法完成的操作的结果类型。例如,在一个函数抛出了异常,或者存在无限循环。使用`never`类型可以更好地定义某些情况下的函数或操作的返回类型,同时帮助我们避免潜在的逻辑错误。 ### 回答3: TypeScript是一种静态类型的编程语言,它可以在JavaScript的基础上添加静态类型检查和一些其他特性。在TypeScript有三种特殊的类型:any、unknown和never。 any类型表示任意类型,它可以用来表示任何类型的值。使用any类型可以绕开类型检查,编译器不会对any类型的值进行类型检查和推断。any类型的变量可以接受任何类型的值,因此在使用any类型时需要特别小心,因为它可能导致类型错误和运行时错误。 unknown类型也表示任意类型,但它比any类型更严格。当使用unknown类型时,编译器会要求进行类型检查和类型断言,以确保类型安全。unknown类型的变量不能直接赋值给其他类型的变量,必须经过类型断言或类型检查后才能进行赋值。这种类型更适合在编写通用代码或处理动态类型的情况下使用,相比any类型unknown类型提供了更加严格的类型安全。 never类型表示永远不会发生的类型。它通常会用在函数的返回类型,表示该函数永远不会正常返回。例如,一个会抛出异常或进入无限循环的函数的返回类型可以设为never。同时,never类型也可以用来处理不可到达的代码块,例如一个带有无限循环的函数的后续代码块。 总而言之,在TypeScript,any类型unknown类型都表示任意类型,但unknown类型更加严格,并且要求进行类型检查和类型断言。而never类型表示永远不会发生的类型,通常用于函数的返回类型或不可到达的代码块。使用这些类型要谨慎,并且根据实际需求来选择合适的类型
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值