问题的背景
在 JavaScript 中,typeof 运算符用于在运行时检查原始值的类型。TypeScript 扩展了这一机制,并通过类型保护(type guards)将其纳入类型缩减(type narrowing)系统中。TypeScript 使用 typeof 运算符的结果来澄清代码块内变量的类型,这使得在处理联合类型时可以更精确地描述函数的逻辑。
问题
在普通的 JavaScript 中,通过 typeof 检查值的类型后,并没有类型保证——程序员必须记住在代码的哪个部分发生了什么。但是,TypeScript 的任务变得复杂,因为存在不同的类型和联合类型,如果没有正确的类型缩减,很容易出错,例如,调用不存在的方法。此外,该运算符还有具体的限制:它只能“看到”基本的原始类型,例如,对数组和对象会返回 'object'。
解决方案
TypeScript 允许将 typeof 运算符与自定义的类型分析结合使用,以便在代码块内缩减变量的类型。这自动提高了安全性——编译器知道代码正在处理的类型,并提示可能的属性和方法。
示例代码:
function printId(id: number | string) { if (typeof id === 'string') { // 在这个分支中 id: string console.log(id.toUpperCase()); } else { // 在这个分支中 id: number console.log(id.toFixed(2)); } }
关键特点:
typeof 运算符能否识别数组?
不能,typeof 对于数组和对象返回相同的值——'object'。要区分数组,最好使用 Array.isArray() 方法。
示例代码:
const arr = [1, 2, 3]; console.log(typeof arr); // 'object' console.log(Array.isArray(arr)); // true
可以用 typeof 区分 null 和对象吗?
不能,typeof null 返回 'object',这是 JavaScript 的历史特性。
示例代码:
console.log(typeof null); // 'object'
可以用 typeof 检查用户定义的类吗?
不能,对于类的实例,typeof 也会返回 'object'。为此使用 instanceof 运算符或自定义类型保护函数。
示例代码:
class User {} const u = new User(); console.log(typeof u); // 'object' console.log(u instanceof User); // true
typeof 检查复杂数据结构(例如,数组、null、对象)。instanceof 和 Array.isArray() 运算符来更精确地缩减类型。程序员编写了一个函数,想通过 typeof 检查 value 是否为数组,并根据结果调用不同的方法。
优点:
缺点:
使用 Array.isArray 并与类型保护结合起来。
优点:
缺点: