基于本文回答

播面 播面

文图音视,全方位拆解八股文
0
评论

typeof 和 instanceof 在类型守卫中如何使用?

知识点图片

在 TypeScript 中,类型守卫 (Type Guards) 是一种通过条件语句检查变量类型,从而在特定代码块中“收窄”变量类型的机制。

typeofinstanceof 是 JavaScript 原生的操作符,TypeScript 能够识别它们并自动进行类型推断。

以下是它们的具体用法和区别:


1. typeof 类型守卫

typeof 主要用于检查基本数据类型(Primitives)。

适用范围

它可以识别以下返回值:

  • "string"
  • "number"
  • "boolean"
  • "symbol"
  • "undefined"
  • "object" (注意:null 和数组也会返回这个,所以通常不用它来精确判断对象)
  • "function"
  • "bigint"

如何使用

通常用于处理联合类型(Union Types),区分不同的基本类型。

typescript
function printId(id: number | string) {
  // 在这个 if 语句之前,id 可能是 number 或 string

  if (typeof id === "string") {
    // 【类型守卫生效】
    // TypeScript 知道在此块中,id 必定是 string 类型
    console.log("ID is string: " + id.toUpperCase()); 
  } else {
    // TypeScript 自动推断在此块中,id 必定是 number 类型
    console.log("ID is number: " + id.toFixed(2));
  }
}

注意事项

  • null 的陷阱typeof null 会返回 "object"。如果你需要判断是否为对象且非 null,不能只用 typeof
  • 数组的陷阱typeof [] 也会返回 "object"

2. instanceof 类型守卫

instanceof 主要用于检查类(Class)的实例构造函数创建的对象。它通过检查对象的原型链来判断。

适用范围

  • 自定义的 class
  • 内置对象(如 Date, RegExp, Array, Error 等)

如何使用

当你的类型是类的联合类型时,使用 instanceof 非常有效。

typescript
class Dog {
  bark() { console.log("Woof!"); }
}

class Cat {
  meow() { console.log("Meow!"); }
}

function interact(pet: Dog | Cat) {
  // pet 可能是 Dog 或 Cat

  if (pet instanceof Dog) {
    // 【类型守卫生效】
    // TypeScript 知道 pet 是 Dog 类型,可以调用 bark
    pet.bark();
    // pet.meow(); // 报错:Dog 类型上不存在 meow 方法
  } else {
    // TypeScript 推断 pet 是 Cat 类型
    pet.meow();
  }
}

用于内置对象

typescript
function logValue(x: Date | string) {
  if (x instanceof Date) {
    console.log(x.toUTCString()); // x 被收窄为 Date
  } else {
    console.log(x.toUpperCase()); // x 被收窄为 string
  }
}

3. 总结与对比

特性 typeof instanceof
检查对象 基本数据类型 (Primitives) 类实例、对象 (Objects)
判断依据 值的底层类型标签 原型链 (Prototype Chain)
常见场景 string vs number vs boolean ClassA vs ClassB,或 Date, Array
局限性 无法区分普通对象、数组和 null (都返回 "object") 无法判断基本类型 (如 123 instanceof Number 为 false)

最佳实践建议

  1. 判断基本类型时:优先使用 typeof
    • 例如:if (typeof x === 'string')
  2. 判断类实例时:优先使用 instanceof
    • 例如:if (x instanceof MyClass)
  3. 判断数组时:不要用 typeof,也不建议用 instanceof Array(虽然可行),推荐使用 Array.isArray(),TypeScript 也能识别它作为类型守卫。
  4. 判断普通对象接口时:如果对象不是通过类创建的(只是普通的 JSON 对象),typeofinstanceof 都无法区分具体的接口形状(Interface)。此时需要使用 自定义类型守卫 (User-Defined Type Guards),即 parameter is Type 语法。

补充:自定义类型守卫示例(当 typeof/instanceof 不够用时)

typescript
interface Fish { swim: () => void; }
interface Bird { fly: () => void; }

// 自定义守卫:判断 pet 是否是 Fish
function isFish(pet: Fish | Bird): pet is Fish {
  return (pet as Fish).swim !== undefined;
}

function move(pet: Fish | Bird) {
  if (isFish(pet)) {
    pet.swim(); // TS 知道这是 Fish
  } else {
    pet.fly();  // TS 知道这是 Bird
  }
}
00:00
00:00