第 5 章:接口
学习目标
- 用 interface 定义对象结构
- 学会可选属性、只读属性、索引签名
- 理解接口继承与合并
- 区分 interface 与 type
一、最基本的接口
typescript
interface User {
id: number;
name: string;
email: string;
}
const tom: User = {
id: 1,
name: 'Tom',
email: 'tom@example.com',
};
// ❌ 少字段会报错
const bad: User = { id: 1, name: 'Tom' };
// Property 'email' is missing in type二、可选属性与只读属性
typescript
interface Config {
host: string;
port?: number; // 可选
readonly apiKey: string; // 只读
}
const cfg: Config = { host: 'localhost', apiKey: 'abc' };
cfg.port = 8080; // ✅ 可选字段可以赋值
cfg.apiKey = 'xyz'; // ❌ Cannot assign to 'apiKey' because it is read-only⚠️ 坑 1:只读属性是编译期保护,运行后通过
Object.assign之类的反射仍可改,真要锁死得用Object.freeze()。
三、函数类型接口
typescript
interface GreetFn {
(name: string): string;
}
const greet: GreetFn = (name) => `Hello, ${name}`;
greet('Tom'); // 'Hello, Tom'四、可索引接口(索引签名)
typescript
// 字符串索引
interface Dict {
[key: string]: string;
}
const dict: Dict = {
name: 'Tom',
email: 'tom@example.com',
};
// 数字索引(类似数组)
interface StringArray {
[index: number]: string;
}
const arr: StringArray = ['a', 'b', 'c'];
arr[0]; // 'a'⚠️ 坑 2:索引签名要求所有显式属性必须兼容其类型,下面这种会报错:
typescript
interface Bad {
[key: string]: string;
age: number; // ❌ number 不兼容 string
}五、接口继承(extends)
typescript
interface Animal {
name: string;
}
interface Dog extends Animal {
breed: string;
}
const d: Dog = {
name: '旺财',
breed: '柴犬',
};
// 多继承
interface Pet {
owner: string;
}
interface Cat extends Animal, Pet {
color: string;
}
const c: Cat = { name: '小花', owner: 'Tom', color: '白' };六、接口合并(Declaration Merging)
同名 interface 会自动合并:
typescript
interface Box {
width: number;
}
interface Box {
height: number;
}
// 等价于:
interface Box {
width: number;
height: number;
}
const b: Box = { width: 10, height: 20 };⚠️ 坑 3:
type不能合并,会报重复定义;interface可以。这在扩展第三方库类型时特别有用。
七、接口继承类
typescript
class Control {
state: number = 0;
}
interface SelectableControl extends Control {
select(): void;
}
class Button extends Control implements SelectableControl {
select(): void {
console.log('selected');
}
}八、interface vs type 速查
| 场景 | 选什么 | 原因 |
|---|---|---|
| 对象/函数结构 | interface | 可继承、可合并,语义清晰 |
| 联合/交叉/元组 | type | interface 表达不了 |
| 工具类型组合 | type | 灵活 |
| 需要 declare merge | interface | type 做不到 |
九、实战:组件 Props
typescript
interface ButtonProps {
label: string;
disabled?: boolean;
onClick: (e: MouseEvent) => void;
variant?: 'primary' | 'secondary' | 'danger';
}
function Button(props: ButtonProps): void {
console.log(props.label);
}
Button({ label: '提交', onClick: (e) => console.log(e) });十、本章小结
| 要点 | 关键 |
|---|---|
| 基本接口 | interface Name { ... } 定义对象结构 |
| 可选 / 只读 | prop? 可选,readonly prop 只读 |
| 索引签名 | [key: string]: T 描述动态 key |
| 继承 | interface B extends A { ... } |
| 合并 | 同名 interface 自动合并 |
| vs type | 对象用 interface,联合/元组/工具用 type |
动手练习
- API 响应:定义
interface ApiResponse<T>,包含code / message / data - 嵌套接口:定义
User,包含address: { city: string; zip: string } - 继承练习:定义
Animal→Dog extends Animal(加bark(): void)
下一章:第 6 章:类型别名与联合 →