TypeScript Interface 用法速查
· 3 min read
Interface 是 TS 定义对象/数组结构的主力工具——核心是 形状契约,不是类继承。
- 对象类型:
interface Person { name; age }限定对象必须有哪些字段 - 可选字段:
name?: string表示可有可无 - 只读字段:
readonly age防止外部修改 - 索引签名:
[key: string]: any描述动态字段 - Duck typing:TS 是结构化类型,多余字段传入不报错
对象类型:核心用法
interface Person {
name: string
age: number
}
const p1: Person = { name: 'Kimi', age: 20 } // OK
const p2: Person = { name: 'Kimi', a: 20 } // Error: 'a' 不存在
const p3: Person = { name: 'Kimi', age: '100' } // Error: age 类型错
接口是形状契约——变量必须按形状填齐字段,多一个少一个都不行。
可选字段 ?
interface Person {
name: string
age: number
gender?: string // 可选
}
const p1: Person = { name: 'Kimi', age: 20 } // OK
const p2: Person = { name: 'Kimi', age: 20, gender: 'm' } // OK
访问可选字段返回 T | undefined,必须先 narrow:
if (p1.gender !== undefined) {
p1.gender.toUpperCase() // OK
}
tip
配合 strictNullChecks(2026 默认开启),可选字段会强制你处理 undefined 情况。
只读字段 readonly
interface Person {
name: string
readonly age: number
}
const p: Person = { name: 'Kimi', age: 20 }
p.age = 18 // Error: Cannot assign to 'age' because it is a read-only property
readonly 是编译期保护,运行时只是普通属性——可以通过类型断言绕过,但不要这么干。
索引签名:动态字段
interface Person {
name: string
age: number
[key: string]: any // 允许任意额外字段
}
const p: Person = { name: 'Kimi', age: 20, gender: 'm', id: 888 }
两种签名:
[key: string]: T—— 字符串 key(默认)[index: number]: T—— 数字 key(数组用法)
warning
所有声明字段的类型必须兼容索引签名的类型。如果索引签名是 number,那所有字段都必须是 number 或 number 的子类型。
interface Bad {
name: string // Error: string 不能赋值给 number 索引类型
[index: number]: number
}
interface vs type:怎么选
| 维度 | interface | type |
|---|---|---|
| 合并 | 自动合并(同名字段) | 不合并,重复声明报错 |
| 联合/交叉 | 只能用 & 合并 | 原生支持联合 |
| 扩展 | extends 多继承 | & 交叉类型 |
| 适配场景 | 对象形状 API、库类型 | 联合类型、复杂类型运算 |
tip
简单对象形状用 interface,需要 union / 复杂运算用 type。两者 80% 场景能互换。
数组用法
用索引签名定义数组类型:
interface StringArray {
[index: number]: string
}
const arr: StringArray = ['a', 'b']
arr[0] = 123 // Error
数组也支持 readonly:
interface ReadonlyStringArray {
readonly [index: number]: string
}
const arr: ReadonlyStringArray = ['a', 'b']
arr[1] = 'c' // Error
warning
现代 TS 优先用 readonly string[] 而不是 interface 索引签名——更简洁,IDE 提示更好。
Duck typing:多余字段不报错
interface Person {
name: string
age: number
}
function handle(p: Person) {
console.log(p.name, p.age)
}
// 通过变量传入:多余字段不报错
const user = { name: 'Kimi', age: 20, gender: 'm' }
handle(user) // OK
// 直接传对象字面量:多余字段报错
handle({ name: 'Kimi', age: 20, gender: 'm' }) // Error
这是 TS 的结构化类型(structural typing):只要对象形状兼容,多余字段无所谓。但对象字面量是"新鲜出炉"的,TS 会做额外属性检查。
References
- TypeScript Handbook: Interfaces —— 官方手册
- TypeScript Handbook: Object Types —— 对象类型详解