面试题答案
一键面试定义方式
- 接口(Interface):使用
interface
关键字定义。例如:
interface User {
name: string;
age: number;
}
- 类型别名(Type Alias):使用
type
关键字定义。例如:
type User = {
name: string;
age: number;
}
区别
- 扩展方式:
- 接口:可以通过
extends
关键字继承其他接口。例如:
- 接口:可以通过
interface Employee extends User {
jobTitle: string;
}
- 类型别名:可以使用交叉类型(
&
)实现类似继承的效果,但语法不同。例如:
type Employee = User & {
jobTitle: string;
}
- 可重复性:
- 接口:可以重复定义,声明合并后会将属性合并。例如:
interface User {
name: string;
}
interface User {
age: number;
}
// User 接口现在有 name 和 age 属性
- 类型别名:不能重复定义,重复定义会报错。
- 适用类型:
- 接口:主要用于定义对象类型结构。
- 类型别名:除了对象类型,还可以用于定义联合类型、交叉类型、函数类型等。例如:
// 联合类型
type StringOrNumber = string | number;
// 函数类型
type AddFunction = (a: number, b: number) => number;
实际前端开发场景适用情况
- 接口适用场景:
- 当主要定义对象的结构,并且可能需要继承和扩展时,接口更合适。例如在定义 React 组件的
props
时,如果有一些通用的props
结构可以被多个组件继承,接口就很有用。
- 当主要定义对象的结构,并且可能需要继承和扩展时,接口更合适。例如在定义 React 组件的
- 类型别名适用场景:
- 当需要定义联合类型、交叉类型或函数类型等复杂类型时,类型别名更方便。比如在处理可能返回不同类型数据的函数返回值时,使用联合类型别名。
场景示例
- 选择接口的场景:
- 假设我们正在开发一个电商网站,有一系列商品展示组件。我们定义一个基本的
Product
接口来描述商品的基本信息。
- 假设我们正在开发一个电商网站,有一系列商品展示组件。我们定义一个基本的
interface Product {
id: number;
name: string;
price: number;
}
// 对于电子产品,可能有额外的属性
interface ElectronicProduct extends Product {
brand: string;
warranty: number;
}
这里使用接口,通过继承可以方便地扩展商品类型,符合面向对象的设计原则,在组件中使用 props
定义时也更直观。
2. 选择类型别名的场景:
- 在处理用户输入的表单数据时,用户可能输入数字或者字符串(比如年龄可能输入数字,也可能输入“未知”字符串)。我们可以使用类型别名定义联合类型。
type AgeInput = string | number;
function handleAgeInput(age: AgeInput) {
// 处理逻辑
}
这种情况下,类型别名更简洁地定义了复杂的类型,接口则无法直接定义这样的联合类型。