返回

类型里的Any是个大坑,如何躲避

前端

在 TypeScript 的世界里,anyunknown 就像一对双胞胎,乍一看很像,但相处久了,就会发现它们的性格截然不同。它们都能包容各种类型的数据,就像一个万能的容器,但 unknown 更像一个谨慎的管家,它会要求你明确告诉它里面装的是什么,才能让你使用;而 any 则像一个随和的老好人,来者不拒,也不多问。

any:灵活但危险的家伙

想象一下,你有一个储物箱,可以存放任何东西,玩具、衣服、书籍,甚至厨房的水槽!这就是 any 的工作方式。它非常灵活,可以容纳任何类型的数据,不需要你提前声明。

let myVariable: any = "Hello, world!"; 
myVariable = 123; 
myVariable = { name: "John", age: 30 }; 

你看,myVariable 可以随意切换身份,一会儿是字符串,一会儿是数字,一会儿又变成了对象。这种灵活性在某些情况下很有用,比如当你处理来自外部数据源的数据,并且不确定数据的具体类型时。

但是,这种灵活性也带来了风险。由于 TypeScript 无法确定 any 变量的实际类型,它就无法进行类型检查。这就好像你从储物箱里摸东西,却不知道会摸到什么,可能会摸到一个柔软的玩具,也可能会摸到一个尖锐的工具。

let myString: any = "Hello";
let myLength: number = myString.length; // 这里不会报错,但如果 myString 不是字符串,就会在运行时出错

在上面的例子中,TypeScript 不会报错,因为它认为 myString 可以拥有 length 属性。但如果 myString 实际存储的是一个数字或者其他没有 length 属性的数据类型,程序就会在运行时崩溃。

unknown:谨慎而安全的卫士

any 不同,unknown 更加谨慎。它也允许你存储任何类型的数据,但它会要求你在使用之前明确声明数据的类型。这就好像你有一个上了锁的保险箱,只有输入正确的密码才能打开。

let mySecret: unknown = "My password";

//  不能直接使用 mySecret
// let myStringLength: number = mySecret.length; //  会报错

//  需要先进行类型检查
if (typeof mySecret === "string") {
  let myStringLength: number = mySecret.length; //  现在可以使用了
}

在上面的例子中,我们必须先检查 mySecret 是否是字符串类型,才能访问它的 length 属性。这种额外的检查步骤虽然看起来有些麻烦,但却可以有效地避免运行时错误,提高代码的安全性。

如何选择 anyunknown

那么,什么时候应该使用 any,什么时候应该使用 unknown 呢?

  • 如果你真的不确定数据的类型,并且不想进行类型检查,可以使用 any。但这通常不是一个好主意,因为它会降低代码的安全性。
  • 如果你不确定数据的类型,但希望在使用之前进行类型检查,可以使用 unknown。这是一种更安全的选择,可以帮助你避免运行时错误。
  • 如果你知道数据的类型,就应该使用具体的类型声明,例如 stringnumberboolean 等等。

总结一下

anyunknown 都是 TypeScript 中强大的工具,但它们的使用场景不同。any 更加灵活,但风险也更大;unknown 更加谨慎,但也更安全。在实际开发中,我们应该根据具体情况选择合适的类型,尽量避免过度使用 any,以提高代码的质量和安全性。

常见问题解答

1. anyunknown 的主要区别是什么?

any 允许你绕过 TypeScript 的类型检查,而 unknown 要求你在使用之前进行类型检查。

2. 什么时候应该使用 any

只有在你真的不确定数据的类型,并且不想进行类型检查的时候才应该使用 any

3. 什么时候应该使用 unknown

如果你不确定数据的类型,但希望在使用之前进行类型检查,可以使用 unknown

4. unknownany 更安全吗?

是的,unknownany 更安全,因为它可以帮助你避免运行时错误。

5. 如何避免过度使用 any

尽量使用具体的类型声明,例如 stringnumberboolean 等等。只有在你真的不确定数据的类型的时候才应该使用 any