TypeScript 接口
在 TypeScript 中,接口(Interface) 是一种定义“形状”的方式 —— 它用来约束对象、函数或者类应该拥有哪些属性和方法。你可以把它理解为一份“契约”:只要符合接口的约定,就能通过类型检查。
接口只存在于编译时,编译成 JavaScript 后会被删除,不会带来任何运行时开销。
接口定义
对象接口
最常见的场景是描述一个普通对象的类型:
// 定义用户接口
interface User {
id: number
name: string
email: string
}
// 使用接口作为类型注解
function greetUser(user: User) {
console.log(`Hello, ${user.name}`)
}
// 传入的对象必须完全符合 User 的形状
const u = { id: 1, name: '张三', email: 'zhangsan@example.com' }
greetUser(u) // ✅ 正确
// 缺少 email 会报错
const u2 = { id: 2, name: '李四' }
greetUser(u2) // ❌ 类型 "{ id: number; name: string; }" 中缺少属性 "email"
核心规则:传入的对象必须拥有接口中声明的所有属性,且类型匹配,不能多也不能少(除非使用了可选属性)。
实际开发中,对象可能有部分属性是可选的,或者一旦创建就不允许修改。
可选属性(?)
使用 ? 标记属性为可选:
interface Product {
id: number
name: string
description?: string // 可选
}
const p1: Product = { id: 1, name: '笔记本' } // ✅ 没有 description 也可以
const p2: Product = { id: 2, name: '手机', description: '旗舰机' } // ✅
只读属性(readonly)
使用 readonly 标记属性为只读,在对象创建后不能修改:
interface Config {
readonly apiUrl: string
timeout: number
}
const config: Config = {
apiUrl: 'https://api.example.com',
timeout: 5000,
}
config.timeout = 6000 // ✅ 可以修改
// config.apiUrl = 'https://new.api.com' // ❌ 无法分配到 "apiUrl",因为它是只读属性
函数类型接口
接口不仅可以描述对象,还可以描述函数类型 —— 定义函数的参数类型和返回值类型。
// 定义一个加法函数接口
interface AddFunction {
(a: number, b: number): number
}
// 使用接口约束函数
const add: AddFunction = (x, y) => x + y
console.log(add(3, 5)) // 8
如果你在项目中封装了一个计算器工具,用接口约束所有计算函数的签名,会非常安全。
接口继承(扩展)
接口之间可以相互继承,复用已有的定义。使用 extends 关键字:
interface Animal {
name: string
age: number
}
interface Dog extends Animal {
breed: string // 新增属性
bark(): void // 新增方法
}
const myDog: Dog = {
name: '旺财',
age: 3,
breed: '金毛',
bark() {
console.log('汪汪!')
},
}
可以继承多个接口:
interface A { a: string }
interface B { b: number }
interface C extends A, B {
c: boolean
}
const obj: C = { a: 'hello', b: 42, c: true }