TypeScript 接口(Interfaces)详解
接口定义对象的结构契约:属性、方法、继承与声明合并。本文讲解接口核心用法、结构类型系统与 interface vs type 的抉择。
接口描述对象"必须长什么样":interface User { id: number; name: string }——任何形状匹配的对象都满足它(结构类型)。纯编译期存在,运行时零成本。interface vs type:对象契约优先 interface(可扩展、错误信息友好),联合/工具类型用 type。
结构契约
interface User {
id: number;
name: string;
email?: string; // 可选
readonly createdAt: Date;
}
function greet(user: User) {
return `你好,${user.name}`;
}
greet({ id: 1, name: '张三' }); // 结构匹配即可——鸭子类型
结构类型系统:不看"声明是什么",看"形状是什么"——任何有 id 和 name 的对象都是 User。
扩展与组合
interface Animal { name: string; }
interface Dog extends Animal { breed: string; }
// 声明合并:同名接口自动合并(扩展第三方类型的机制)
interface Window { myAppConfig: Config }
声明合并是 interface 独有——扩展库的类型(Express Request 加 user 字段)依赖它。
函数签名
interface Formatter {
(value: number): string; // 调用签名
currency: string; // 函数还可以有属性
}
const cny: Formatter = Object.assign(
(v: number) => `¥${v.toFixed(2)}`,
{ currency: 'CNY' }
);
interface vs type
| 能力 | interface | type |
|---|---|---|
| 对象形状 | ✓ | ✓ |
| 联合/交叉/工具类型 | ✗ | ✓ |
| 声明合并 | ✓ | ✗ |
| extends 性能(大型项目) | 略优 | — |
实践共识:对象契约用 interface,其余用 type——两者重叠区按团队规范统一即可。
常见问题(FAQ)
Q:接口能实现(implements)吗?
能——class UserService implements Service 让类承诺契约。依赖注入风格的代码库重度使用。
Q:多余属性检查是怎么回事?
对象字面量直接传入时会检查多余属性(freshness 规则);先赋给变量再传则只看形状兼容——这是特性不是 bug,防止拼错属性名。
Q:接口描述数组/索引?
可以:interface StringList { [i: number]: string }——见本系列《索引签名》。
参考文档
本文依据公开文档整理,示例需按项目依赖版本验证;不将文档中的性能描述视为本项目实测结果。