TypeScript 接口 interface
一、什么是接口
接口就是结构契约,规定对象、类应当具备哪些属性、方法,不关心具体实现,只定义 "长什么样"。
接口不会编译出 JS 代码,仅在 TS 编译阶段做类型校验。
1. 接口约束对象结构
typescript
interface Person {
name: string;
age: number;
speak(): void;
}
// 对象必须完全符合接口结构
let p: Person = {
name: "张三",
age: 18,
speak() {
console.log("你好");
},
};
2. 类实现接口 implements
类通过implements关键字实现接口,类必须实现接口中全部的属性与方法,少写会直接报类型错误。
typescript
// 定义接口
interface Person {
name: string;
age: number;
speak(): void;
}
// Teacher类实现Person接口
class Teacher implements Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
speak(): void {
console.log(`我是老师:${this.name}`);
}
}
注意:接口只做约束,不会提供任何方法实现,所有方法都要类自己写。
二、接口可重复声明合并
interface支持重复声明,自动合并属性和方法 ,这是type做不到的。
typescript
interface PersonInter {
name: string;
age: number;
}
// 再次声明同名接口,TS自动合并
interface PersonInter {
speak(): void;
}
// 使用的时候,同时拥有 name、age、speak
class Person implements PersonInter {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
speak(): void {
console.log("hello");
}
}
如果重复声明出现同名属性但是类型不一致,会直接报错。
三、interface vs type 自定义类型
interface和type二者有明确区别。
相同点
都可以描述对象结构,都可以用来做变量的类型注解。
typescript
// 接口写法
interface IPerson {
name: string;
age: number;
}
// type自定义类型写法
type TPerson = {
name: string;
age: number;
};
// 二者都可以约束对象变量
let obj1: IPerson = { name: "a", age: 10 };
let obj2: TPerson = { name: "b", age: 10 };
核心区别
| 特性 | interface | type |
|---|---|---|
| 重复声明合并 | ✅ 支持,同名自动合并 | ❌ 不允许重复定义 |
| 约束类(implements) | ✅ 可以被类实现 | ❌ 不能被类 implements |
| 联合类型、交叉、基础类型别名 | ❌ 不支持 | ✅ 支持,type A = number|string |
| 继承扩展 | 使用extends继承其他接口 |
使用&交叉类型 |
开发建议:
- 描述类、对象结构,未来可能扩展合并 优先用
interface- 需要联合类型、元组、给基础类型起别名,优先用
type
四、interface 接口 vs abstract class 抽象类
这两个都可以约束类结构,但是底层完全不一样。
抽象类 abstract class
- 使用
extends关键字继承; - 里面可以写普通实例方法(有具体实现),也可以写抽象方法;
- 抽象类不能 new 实例;
- 可以有构造函数,可以有属性修饰符 (
private/protected/public)。
typescript
abstract class Person {
name: string;
constructor(name: string) {
this.name = name;
}
// 抽象方法,子类必须实现
abstract speak(): void;
// 普通方法,自带实现,子类直接复用
walk() {
console.log("走路");
}
}
class Teacher extends Person {
speak(): void {
console.log(this.name + "在说话");
}
}
interface 接口
- 类使用
implements关键字实现接口; - 只能声明方法签名,不能写方法实现;
- 没有构造函数;
- 没有
private/protected修饰,只能是公开成员。
typescript
interface IPerson {
name: string;
speak(): void;
}
class Teacher implements IPerson {
name: string;
speak(): void {
console.log("说话");
}
}
对比表格
| 对比项 | 抽象类 abstract class | 接口 interface |
|---|---|---|
| 使用关键字 | extends继承 |
implements实现 |
| 方法 | 可包含普通方法(带实现)+ 抽象方法 | 只能是抽象签名,无实现 |
| 构造函数 | ✅ 有 constructor | ❌ 不能写构造器 |
| 访问修饰符 | private/protected/public | 只能 public |
| JS 产物 | 编译后会生成真实 JS 类代码 | 编译后完全消失,无 JS 代码 |
使用场景:
- 需要复用一部分公共逻辑、公共方法 → 选抽象类继承
extends- 只需要做结构契约,不提供任何逻辑复用 → 选接口
implements
五、extends 接口继承
接口可以继承另一个接口,复用已有结构。
typescript
interface Animal {
name: string;
}
// Dog接口继承Animal,拥有name,新增age、bark
interface Dog extends Animal {
age: number;
bark(): void;
}
let dog: Dog = {
name: "旺财",
age: 3,
bark() {
console.log("汪汪汪");
},
};
六、总结
- 接口仅 TS 阶段有效,编译为 JS 之后全部消失,不要试图在 JS 运行时拿接口。
implements是类去实现接口;extends用于类继承类、接口继承接口,不要搞混关键字。interface重复合并,属性同名类型不一致直接报错。- 接口里面不能写方法具体实现,全部是声明;抽象类可以写完整方法。
- type 不能被
implements,不要用 type 代替接口去约束类。
七、什么时候用接口?
- 定义后端返回数据对象结构;
- 定义类应当遵守的行为契约,多个类需要遵守同一套规范;
- 库、组件开发,对外暴露对外的类型契约,方便使用者扩展。
interface、type、abstract class三者不是互斥,项目中经常组合使用。