前后端面试题》专栏集合了前后端各个知识模块的面试题,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs,nodejs,mangoDB,SQL,Linux… 。

前后端面试题-专栏总目录

在这里插入图片描述

一、本文面试题目录

81. 什么是类型守卫(Type Guard)?它的核心作用是什么?

  • 原理说明:类型守卫(Type Guard)是TypeScript中一种特殊的表达式,用于在特定作用域内缩小变量的类型范围(即类型收窄)。它通过特定语法或逻辑判断,让TypeScript编译器能够确定变量的具体类型,从而避免类型错误。
  • 核心作用:在联合类型等场景中,明确变量的具体类型,使开发者可以安全地访问该类型特有的属性或方法,无需额外的类型断言。
  • 示例代码
    type StringOrNumber = string | number;
    
    function isString(value: StringOrNumber): value is string {
      return typeof value === 'string';
    }
    
    function logValue(value: StringOrNumber) {
      if (isString(value)) {
        // 类型收窄为string,可安全调用string方法
        console.log(value.toUpperCase()); 
      } else {
        // 类型收窄为number,可安全调用number方法
        console.log(value.toFixed(2)); 
      }
    }
    

82. typeof类型守卫的局限性是什么?它能识别哪些类型?

  • 原理说明typeof类型守卫通过typeof 变量的结果判断变量类型,是TypeScript内置的基础类型守卫。
  • 可识别的类型:仅能准确识别stringnumberbooleansymbolbigintfunctionundefined这7种类型。
  • 局限性
    • 无法区分nullobjecttypeof null返回"object")。
    • 无法识别具体的对象类型(如ArrayDate等,typeof []返回"object")。
    • 对自定义类型(如类实例)无能为力。
  • 示例代码
    function checkType(value: any) {
      if (typeof value === 'string') {
        console.log('是字符串'); // 正确识别
      } else if (typeof value === 'number') {
        console.log('是数字'); // 正确识别
      } else if (typeof value === 'object') {
        // 无法区分null、数组、普通对象等
        console.log('可能是对象、数组或null'); 
      }
    }
    

83. instanceof类型守卫的作用是什么?它适用于哪些场景?

  • 原理说明instanceof类型守卫通过判断对象是否为某个构造函数的实例(即是否由该构造函数创建),来收窄变量类型。它基于原型链的继承关系工作。
  • 适用场景
    • 区分不同类的实例(如DateArray或自定义类)。
    • 处理基于类的继承体系中的类型判断。
  • 示例代码
    class Dog {
      bark() { console.log('汪汪'); }
    }
    
    class Cat {
      meow() { console.log('喵喵'); }
    }
    
    function animalSound(animal: Dog | Cat) {
      if (animal instanceof Dog) {
        animal.bark(); // 类型收窄为Dog
      } else {
        animal.meow(); // 类型收窄为Cat
      }
    }
    
    // 对内置对象的判断
    function handleValue(value: Date | Array<any>) {
      if (value instanceof Date) {
        console.log(value.toISOString()); // 类型收窄为Date
      } else {
        console.log(value.length); // 类型收窄为Array
      }
    }
    

84. 如何自定义类型守卫函数?语法是什么?举例说明。

  • 原理说明:自定义类型守卫函数是开发者手动定义的函数,返回值类型为“参数 is 目标类型”的布尔值,用于告诉TypeScript如何收窄变量类型。
  • 语法function 函数名(参数: 联合类型): 参数 is 目标类型 { ... }
  • 示例代码
    type Fish = { swim: () => void };
    type Bird = { fly: () => void };
    
    // 自定义类型守卫:判断是否为Fish
    function isFish(animal: Fish | Bird): animal is Fish {
      return 'swim' in animal; // 通过是否有swim属性判断
    }
    
    function move(animal: Fish | Bird) {
      if (isFish(animal)) {
        animal.swim(); // 类型收窄为Fish
      } else {
        animal.fly(); // 类型收窄为Bird
      }
    }
    
    // 更复杂的判断逻辑
    type User = { role: 'user'; name: string };
    type Admin = { role: 'admin'; id: number };
    
    function isAdmin(person: User | Admin): person is Admin {
      return person.role === 'admin';
    }
    

85. in操作符如何作为类型守卫使用?举例说明。

  • 原理说明in操作符用于检查对象是否包含某个属性(属性名 in 对象),TypeScript会根据该判断自动收窄变量类型,因此可作为类型守卫使用。
  • 适用场景:区分具有不同属性的联合类型成员。
  • 示例代码
    type Car = { drive: () => void };
    type Boat = { sail: () => void };
    
    function moveVehicle(vehicle: Car | Boat) {
      if ('drive' in vehicle) {
        // 存在drive属性,类型收窄为Car
        vehicle.drive(); 
      } else {
        // 不存在drive属性,类型收窄为Boat
        vehicle.sail(); 
      }
    }
    
    // 处理可选属性
    type WithName = { name?: string };
    type WithoutName = {};
    
    function checkName(obj: WithName | WithoutName) {
      if ('name' in obj) {
        // 类型收窄为WithName,可安全访问name(可能为undefined)
        console.log(obj.name?.toUpperCase()); 
      }
    }
    

86. 什么是“discriminated union”(可区分联合)?如何用它实现自动类型收窄?

  • 原理说明:可区分联合(discriminated union)是一种特殊的联合类型,其成员包含一个共同的“区分属性”(通常是字面量类型),TypeScript可通过该属性自动收窄类型,无需额外类型守卫。
  • 实现条件
    1. 联合类型的每个成员都有一个相同的属性(如type)。
    2. 该属性的值为字面量类型(如字符串、数字),且各成员的值不同。
  • 示例代码
    // 定义可区分联合
    type Circle = { kind: 'circle'; radius: number };
    type Square = { kind: 'square'; sideLength: number };
    type Triangle = { kind: 'triangle'; base: number; height: number };
    type Shape = Circle | Square | Triangle;
    
    // 自动类型收窄
    function getArea(shape: Shape): number {
      switch (shape.kind) {
        case 'circle':
          // 自动收窄为Circle,可访问radius
          return Math.PI * shape.radius **2;
        case 'square':
          // 自动收窄为Square,可访问sideLength
          return shape.sideLength** 2;
        case 'triangle':
          // 自动收窄为Triangle,可访问base和height
          return (shape.base * shape.height) / 2;
      }
    }
    

87. is关键字在类型守卫中的作用是什么?

  • 原理说明is关键字是自定义类型守卫函数的核心,用于声明“当函数返回true时,参数的类型为is右侧指定的类型”。它建立了函数返回值与参数类型之间的关联,让TypeScript能够根据函数的返回结果收窄参数类型。
  • 作用
    • 明确告诉编译器类型判断逻辑,实现自定义的类型收窄规则。
    • 使类型守卫函数的返回值具备“类型断言”的效果,替代手动的as断言。
  • 示例代码
    type A = { a: number };
    type B = { b: string };
    
    // 没有is关键字:仅返回布尔值,无法收窄类型
    function hasA(obj: A | B): boolean {
      return 'a' in obj;
    }
    
    // 有is关键字:返回值关联类型,可收窄类型
    function isA(obj: A | B): obj is A {
      return 'a' in obj;
    }
    
    function handle(obj: A | B) {
      if (hasA(obj)) {
        // 错误:TypeScript无法确定obj是A
        // console.log(obj.a); 
      }
      if (isA(obj)) {
        // 正确:类型收窄为A
        console.log(obj.a); 
      }
    }
    

88. 如何用类型守卫处理联合类型中的nullundefined

  • 原理说明nullundefined常作为联合类型的成员(如string | null),类型守卫可通过判断排除这两种类型,收窄为有效类型。
  • 常见方式
    • 使用!== null!== undefined直接判断。
    • 使用typeoftypeof value !== 'undefined')。
    • 自定义类型守卫函数(如isNotNull)。
  • 示例代码
    type MaybeString = string | null | undefined;
    
    // 方式1:直接判断排除null/undefined
    function logIfValid(value: MaybeString) {
      if (value !== null && value !== undefined) {
        console.log(value.toUpperCase()); // 类型收窄为string
      }
    }
    
    // 方式2:自定义类型守卫
    function isNotNullish<T>(value: T | null | undefined): value is T {
      return value !== null && value !== undefined;
    }
    
    function process(value: MaybeString) {
      if (isNotNullish(value)) {
        console.log(value.length); // 类型收窄为string
      } else {
        console.log('值为null或undefined');
      }
    }
    

89. 什么是“断言函数”(Assertion Functions)?如何定义?与类型守卫的区别?

  • 原理说明:断言函数(Assertion Functions)是一种特殊函数,用于强制断言参数的类型,如果断言失败会抛出错误。它的作用是“确保参数一定是某个类型”,而非“判断参数可能是某个类型”。
  • 定义语法:返回值类型为asserts 参数 is 目标类型
  • 与类型守卫的区别
    特性类型守卫函数断言函数
    返回值boolean无(或抛出错误)
    作用可能为目标类型(条件判断)必须为目标类型(强制断言)
    失败处理不抛出错误,走else逻辑必须抛出错误
  • 示例代码
    type PositiveNumber = number;
    
    // 断言函数:确保参数是正数,否则抛出错误
    function assertPositive(n: number): asserts n is PositiveNumber {
      if (n <= 0) {
        throw new Error('必须是正数');
      }
    }
    
    function calculate(n: number) {
      assertPositive(n); 
      // 断言成功后,n的类型收窄为PositiveNumber
      console.log('平方根:', Math.sqrt(n)); 
    }
    
    calculate(4); // 正常执行
    calculate(-1); // 抛出错误
    

90. 类型收窄的“控制流分析”指什么?TypeScript如何根据条件语句收窄类型?

  • 原理说明:控制流分析(Control Flow Analysis)是TypeScript编译器跟踪变量在不同代码分支(如ifelseswitch、循环等)中的类型变化,并自动收窄类型的过程。它模拟代码的执行路径,推断变量在特定分支中的具体类型。
  • TypeScript的收窄方式
    1. 条件判断:通过if (condition)中的条件(如typeofinstanceofin等)收窄类型。
    2. 逻辑运算符&&||!等逻辑判断影响类型(如if (!value)排除null/undefined)。
    3. switch语句:根据case分支的判断收窄类型(尤其适用于可区分联合)。
    4. throw/return:在分支中抛出错误或返回时,后续代码的类型会相应收窄。
  • 示例代码
    type Value = string | number | null;
    
    function processValue(v: Value) {
      if (v === null) {
        console.log('值为null');
        return; // 此处返回后,后续代码中v不可能为null
      }
      // 控制流分析:v的类型收窄为string | number
      if (typeof v === 'string') {
        // 收窄为string
        console.log(v.length);
      } else {
        // 收窄为number
        console.log(v.toFixed(1));
      }
    }
    
    // switch语句中的控制流分析
    type Fruit = 'apple' | 'banana' | 'orange';
    function getColor(f: Fruit) {
      switch (f) {
        case 'apple':
          return 'red';
        case 'banana':
          return 'yellow';
        // case 'orange': 若注释此行,TypeScript会提示缺少分支
        default:
          const _exhaustiveCheck: never = f;
          return _exhaustiveCheck;
      }
    }
    

二、100道TypeScript面试题目录列表

文章序号TypeScript面试题100道
1TypeScript面试题及详细答案100道(01-10)
2TypeScript面试题及详细答案100道(11-20)
3TypeScript面试题及详细答案100道(21-30)
4TypeScript面试题及详细答案100道(31-40)
5TypeScript面试题及详细答案100道(41-50)
6TypeScript面试题及详细答案100道(51-60)
7TypeScript面试题及详细答案100道(61-70)
8TypeScript面试题及详细答案100道(71-80)
9TypeScript面试题及详细答案100道(81-90)
10TypeScript面试题及详细答案100道(91-100)
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐