什么是 TypeScript 的 unknown 类型?和 any 类型有什么区别?

2024-08-26 15:29:27 481
`unknown` 类型是 TypeScript 中的一种顶级类型,它表示未知的类型。与 `any` 类似,`unknown` 可以表示任意类型的值,但与 `any` 不同的是,使用 `unknown` 会强制你在对其进行操作之前先进行类型检查或类型断言,从而提高了类型安全性。

unknownany 的区别

  1. 类型安全性:

    • any 是完全不受限制的,可以对其进行任何操作(调用方法、访问属性等),而不会有类型检查。这可能导致运行时错误。
    • unknown 是受限制的,在对 unknown 类型的值进行任何操作之前,必须先进行类型检查或类型断言。
  2. 默认类型检查:

    • any 取消了所有的类型检查,使用 any 的地方 TypeScript 不会提供类型错误提示。
    • unknown 保留了类型检查的能力,要求开发者先明确知道类型,然后再进行操作。

示例 1: any 的不安全操作

let anything: any = "hello";
anything.toFixed();  // 运行时错误:因为字符串没有 `toFixed` 方法

解释:

  • 尽管 "hello" 是字符串,但由于使用了 any,TypeScript 允许你调用 toFixed() 方法,这会导致运行时错误。

示例 2: unknown 的类型安全

let unknownValue: unknown = "hello";

// 直接调用 `toFixed` 会报错
// unknownValue.toFixed();  // 编译时错误

if (typeof unknownValue === "number") {
    // 现在 TypeScript 知道 unknownValue 是 number 类型
    console.log(unknownValue.toFixed(2));
} else {
    console.log("不是数字类型");
}

解释:

  • unknownValue 的类型是 unknown,TypeScript 不允许直接调用 toFixed,必须先检查类型。
  • 只有在确认 unknownValuenumber 类型后,才能调用 toFixed 方法,这样可以避免运行时错误。

示例 3: 类型断言与 unknown

let someValue: unknown = "hello";
let strLength: number = (someValue as string).length;  // 类型断言

console.log(strLength);  // 输出: 5

解释:

  • 使用类型断言 (someValue as string) 告诉 TypeScript someValue 是字符串类型,然后再访问字符串的 length 属性。

何时使用 unknown 而不是 any

  • 使用 unknown: 当你确实不确定某个值的类型,但仍然希望保持类型检查的严格性时,应使用 unknown
  • 使用 any: 如果你需要完全绕过 TypeScript 的类型检查机制,可以使用 any,但这通常是不推荐的。

总结

unknownany 都可以表示任意类型的值,但 unknown 是更安全的选择,因为它要求在对值进行操作之前进行类型检查或类型断言,从而减少了潜在的运行时错误风险。