查看原文
其他

【第1847期】理解TypeScript 中 any 和 unknown

广州peen 前端早读课 2020-10-12

前言

ts,大家有空还是可以多学一下。今日早读文章由@penn授权分享。

正文从这开始~~

在我们的项目中实现 TypeScript 时,我们努力写出最好的类型。我们可能经常觉得使用any类型违背了 TypeScript 的目的,确实如此。还有其他一些类型值得了解,我们可能会发现它们在尝试不使用 any 时很有用,比如 unknown 。

Any

any 类型类似于纯 JavaScript 的工作方式。我们有时可能需要描述一个我们根本不知道类型的变量。

  1. let uncertain: any = 'Hello world'!;

  2. uncertain = 5;

  3. uncertain = { hello: () => 'Hello world!'};

在 TypeScript 中,任何东西可以赋值给 any 。它通常被称为 top type 。

以这种方式编写代码似乎不太合适。它是不可预测的,很难维持。您可能觉得在处理一些没有为其创建类型的第三方库时需要使用它,而且您不确定它们是如何工作的。另外,使用 any 可以将 TypeScript 添加到现有的 JavaScript 代码库中。

译者: any 和 unknown 的最大区别是, unknown 是 top type (任何类型都是它的 subtype) , 而 any 即是 top type, 又是 bottom type (它是任何类型的 subtype ) ,这导致 any 基本上就是放弃了任何类型检查.

通过使用 any,我们破坏了 TypeScript 的能力引起了一些麻烦。没有强制的类型检查,可能会给您带来一些麻烦。

  1. const uncertain: any = 'Hello world!';

  2. uncertain.hello();

好了,一个错误已经准备好发布到生产环境了! 上面的例子很生动,但它可能更微妙。比如下面:

  1. const dog: any = {

  2. name: 'Fluffy',

  3. sayHello: () => 'woof woof'

  4. };


  5. dog.hello();

这样子, 一个更细微的错误也发布到生产环境了.

Unknown

TypeScript 3.0中引入的 unknown 类型也被认为是 top type ,但它更安全。与 any 一样,所有类型都可以分配给unknown。

  1. let uncertain: unknown = 'Hello'!;

  2. uncertain = 12;

  3. uncertain = { hello: () => 'Hello!'};

我们只能将 unknown 类型的变量赋值给 any 和 unknown。

  1. let uncertain: unknown = 'Hello'!;

  2. let notSure: any = uncertain;

它确实在很多方面不同于 any 类型。如果不缩小类型,就无法对 unknown 类型执行任何操作。

  1. function getDog() {

  2. return'22'

  3. }


  4. const dog: unknown = getDog();

  5. dog.hello(); //Object is of type 'unknown'

使用类型断言缩小未知范围.

上述机制具有很强的预防性,但对我们的限制过于有限。要对未知类型执行某些操作,首先需要使用类型断言来缩小范围。

  1. const getDogName = () => {

  2. let x: unknown;

  3. return x;

  4. };


  5. const dogName = getDogName();

  6. console.log((dogName asstring).toLowerCase());

在上面的代码中,我们强制TypeScript编译器相信我们知道自己在做什么。

以上的一个重要缺点是它只是一个假设。它没有运行时效果,也不能防止我们在不小心的情况下造成错误。比如下面的代码, 他实际上是错误的, 但却可以通过 typescript 的检测.

  1. const number: unknown = 15;

  2. (number asstring).toLowerCase();

TypeScript编译器接收到我们的数字是一个字符串的假设,因此它并不反对这样处理它。

使用类型收缩

一种更类型安全的缩小未知类型的方法是使用 类型收缩 。TypeScript 编译器会分析我们的代码,并找出一个更窄的类型。

  1. const dogName = getDogName();

  2. if(typeof dogName === 'string') {

  3. console.log(dogName.toLowerCase());

  4. }

在上面的代码中,我们在运行时检查了 dogName 变量的类型。因此,我们可以确保只在 dogName 是变量时调用 toLowerCase函数。

除了使用 typeof,我们还可以使用 instanceof 来缩小变量的类型。

  1. type getAnimal = () => unknown;


  2. const dog = getAnimal();


  3. if(dog instanceofDog) {

  4. console.log(dog.name.toLowerCase());

  5. }

在上面的代码中,我们确保只有在变量是某个原型的实例时才调用dog.name.toLowerCase。TypeScript编译器理解这一点,并假设类型。

关于类型收缩, 更多的可以看 typescript 最佳实践

总结

在本文中,我们已经讨论了any和unknown之间的区别。从以上比较中得出的结论是,unknown 类型要安全得多,因为它迫使我们执行额外的类型检查来对变量执行操作。

关于本文 译者:@peen 译文:https://zhuanlan.zhihu.com/p/104296850 作者:@wanago_io 原文:https://wanago.io/2020/01/27/understanding-any-and-unknown-in-typescript-difference-between-never-and-void/

为你推荐


【第1838期】TypeScript 3.8 Beta


【第1837期】未来可期的TypeScript


【图书】深入理解TypeScript

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存