Appearance
接口
在 TypeScript 中,接口是定义对象结构的强大方式。它不仅在面向对象编程中扮演着核心角色,也是描述数据形状的首选工具。
1. 面向对象中的接口
接口可以看作是比抽象类更纯粹的“契约”。它只声明结构(属性和方法),而不提供任何具体实现。
基本用法
通过 interface 定义结构,类使用 implements 关键字来实现接口:
typescript
interface Foo {
name: string;
get nameGetter(): string;
method(name: string): string;
}
interface Bar {
show(addr: string): string;
}
// 类可以实现多个接口
class Baz implements Foo, Bar {
name = 'baz';
get nameGetter(): string {
return this.name;
}
method(name: string): string {
return name;
}
show(addr: string): string {
return addr;
}
}核心特性
- 关键字:类使用
implements实现接口。 - 多实现:一个类可以同时实现多个接口,弥补了类单继承的局限。
- 无访问修饰符:接口中的成员默认为
public,不能使用private、protected或static。 - 接口继承:接口之间可以使用
extends继承,且支持多继承。
编译说明:抽象类在编译后会保留一个空的 JavaScript 类,而
interface在编译后会被完全移除(类型擦除),不会产生任何运行时的代码。
2. 作为类型声明使用
对于纯前端开发而言,接口常被用作描述对象形状的工具,其心智负担比 type 更低。
typescript
interface User {
readonly id: number; // 只读属性
name: string;
age?: number; // 可选属性
show: (addr: string) => void;
}
const u: User = {
id: 1,
name: 'ruby',
show(addr: string): void {
console.log(addr);
},
};
// u.id = 2; // Error: Cannot assign to 'id' because it is a read-only property.3. 声明合并
这是 interface 区别于 type 的重要特性之一。TypeScript 会自动将多个同名的接口声明合并为一个。
typescript
interface User {
readonly id: number;
name: string;
}
interface User {
age: number;
}
// 合并后的 User 接口同时拥有 id, name 和 age
const u: User = {
id: 1,
name: 'ruby',
age: 18,
};注意:合并时,同名属性的类型必须一致,否则会报错。
4. 接口的继承与扩展
接口可以通过 extends 继承其他接口或类型别名。
继承接口
typescript
interface Animal {
name: string;
}
interface Dog extends Animal {
bark(): void;
}继承类型别名
typescript
type Action = {
type: string;
};
interface UserAction extends Action {
payload: any;
}接口 vs 交叉类型
虽然可以使用 & (交叉类型) 模拟继承,但 extends 在性能和错误提示上通常更优:
typescript
// 接口方式 (推荐)
interface Person extends UserAction {
sex: '男' | '女';
}
// 交叉类型方式
type PA = Person & Action & { sex: '男' | '女' };5. 总结:Interface vs Type
| 特性 | Interface | Type Alias |
|---|---|---|
| 定义对象 | 支持 | 支持 |
| 定义基本类型 | 不支持 | 支持 |
| 声明合并 | 支持 | 不支持 |
| 继承方式 | extends | & (Intersection) |
| 计算属性 | 不支持 | 支持 |
建议:在定义对象结构时,优先使用 interface;在定义联合类型、原始类型别名或需要复杂类型运算时,使用 type。
