MST

星途 面试题库

面试题:深入探究TypeScript中type与interface在类型推断及泛型场景下的区别

在复杂的泛型和类型推断场景下,type和interface表现出不同的行为。请描述在泛型约束、条件类型与映射类型中,type和interface的具体差异,并结合实际代码示例解释如何根据场景选择更合适的方式,以优化代码的可读性与可维护性。
13.7万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

1. 泛型约束

  • interface:接口在泛型约束时,主要通过在接口定义中声明类型参数来约束。例如:
interface KeyValuePair<TKey, TValue> {
  key: TKey;
  value: TValue;
}
function getValue<K, V>(pair: KeyValuePair<K, V>): V {
  return pair.value;
}
  • type:类型别名在泛型约束时同样声明类型参数。例如:
type KeyValuePair<TKey, TValue> = {
  key: TKey;
  value: TValue;
};
function getValue<K, V>(pair: KeyValuePair<K, V>): V {
  return pair.value;
}
  • 差异:在泛型约束方面,二者基本行为一致,都能很好地实现对泛型类型的约束。选择上可基于个人喜好或团队习惯,若注重面向对象风格,interface 稍显直观;若追求简洁表达,type 更合适。

2. 条件类型

  • interface:接口本身不能直接定义条件类型。因为接口旨在定义结构,而条件类型是根据条件动态生成类型。
  • type:类型别名可以方便地定义条件类型。例如:
type IsString<T> = T extends string ? true : false;
type StringCheck = IsString<string>; // true
type NumberCheck = IsString<number>; // false
  • 差异:在条件类型场景下,type 具有明显优势,能够灵活地根据不同条件生成不同类型,interface 则无法胜任。所以当需要根据条件动态生成类型时,应选择 type。

3. 映射类型

  • interface:接口不能直接定义映射类型。接口的定义方式是固定结构的声明,不支持像映射类型那样对已有类型进行变换。
  • type:类型别名可以轻松定义映射类型。例如:
type User = {
  name: string;
  age: number;
};
type ReadonlyUser = {
  readonly [P in keyof User]: User[P];
};
let readonlyUser: ReadonlyUser = { name: 'John', age: 30 };
// readonlyUser.name = 'Jane'; // 报错,只读属性不能重新赋值
  • 差异:在映射类型方面,type 能够实现对已有类型的属性进行遍历、变换等操作,而 interface 不具备此能力。所以当需要对类型的属性进行映射变换时,type 是唯一选择。

总结

  • 若只是定义简单的泛型结构,interface 和 type 均可,可依个人或团队风格选择。
  • 当涉及条件类型或映射类型等复杂类型操作时,应优先选择 type,以提高代码的可读性与可维护性,因为 type 在这些场景下功能更强大且表达更简洁。