原文地址:https://levelup.gitconnected.com/typescript-difference-between-any-and-unknown-types-1fff4bf232a
我们知道,TypeScript 定义了很多基本数据类型:
boolean
:true
或者false
number
: 所有数字类型string
: 字符串类型,使用引号包围,例如'TypeScript is Awesome'any
: 禁用类型检查,允许使用任意类型unknown
: 类似any
但更安全never
: 在使用定义时会抛出一个错误
或许你会对上面描述的any
和unknown
有疑问。这篇文章就是为了解答你的疑问的。
any
和unknown
有两个主要区别:
TypeScript 强制要求在使用unknown
之前必须确定其具体类型,而any
不需要。
例如,
let anyValue: any = 1; let unknownValue: unknown = 1; anyValue.helloworld(); // 没有错误 unknownValue.helloWorld(); // TypeScript 错误
不能把unknown
赋值给除自己或者any
类型以外的其它变量,而any
可以赋值给任意变量。
例如,
let anyValue: any = 1; let unknownValue: unknown = 1; let str: string; str = anyValue; // 没有错误 str = unknownValue; // TypeScript 错误
正如上面描述的那样,这些约束确保在使用unknown
类型之前,必须进行验证。这对减少运行时错误有重要意义。
下面我们看一些用例。
对未知值进行建模
我们可以使用unknown
类型描述未知的值。例如,从网络请求返回的值:
let data: unknown = getSomeValueFromSomeWhere(); if (typeof data === 'string') { //data is a string. } else if (Array.isArray(data)) { //data is an array. } else if (typeof data === 'object') { //data is an object. }
类型断言
在 TypeScript 中,类型断言用于告知编译器一个变量的类型。类型断言类似类型转换,但不需要改造代码。我们通过类型断言告诉编译器变量的类型,从而不需要编译器自己推断类型。但是,我们不能简单地断定一个值可以是我们需要的任意类型。我们不能断言一个值是不匹配其实际值的类型。
例如,
let value = '1' as number; // 错误,我们不能说 string 是 number 类型的 interface Vehicle { name: string; model: string; } function buyVehicle(vehicle: Vehicle){} buyVehicle({niceVehicle: ''} as Vehicle); // 错误,这个对象没有 Vehicle 所要求的必备字段
一个变通方案是,在将一个值转换成某个与实际不匹配的类型时,现将这个值转换成unknown
类型:
buyVehicle({niceVehicle: ''} as unknown as Vehicle)
当然,我们不应该写这样的代码,因为这很容易带来运行时错误。
总结一下,any
和unknown
类型都是 TypeScript 的基本类型。它们是很相似,但也有一些不同。
any
可以很容易绕过类型错误,因为它实际禁止了类型检查,但这么一来,TypeScript 也就不能保证类型安全,同时,所有依赖于类型的工具,比如自动补全,都不能正常工作。
当我们不知道数据的类型时,unknown
往往是最好的选择。在后面使用时,我们需要进行类型转换。
提醒一点,我们应该尽可能地少用any
。