声明合并是 TypeScript 将多个同名声明合并为一个定义的机制。声明合并让接口、命名空间等可以分散定义,然后自动合并。
同名接口会自动合并。
interface User {
id: number
name: string
}
interface User {
email: string
age: number
}
const user: User = {
id: 1,
name: "张三",
email: "zhangsan@example.com",
age: 25
}
合并后的接口包含所有成员。
非函数成员必须唯一,否则类型必须相同。
interface User {
id: number
name: string
}
interface User {
id: number
email: string
}
如果 id 类型不同,会报错。
函数成员会被重载。
interface Document {
createElement(tag: string): HTMLElement
}
interface Document {
createElement(tag: "canvas"): HTMLCanvasElement
createElement(tag: "div"): HTMLDivElement
}
const canvas = document.createElement("canvas")
const div = document.createElement("div")
合并后的接口有多个重载签名。
同名命名空间会合并。
namespace App {
export interface User {
id: number
name: string
}
}
namespace App {
export interface Product {
id: number
name: string
price: number
}
}
const user: App.User = { id: 1, name: "张三" }
const product: App.Product = { id: 1, name: "商品", price: 99.99 }
合并后的命名空间包含所有导出成员。
命名空间可以与类合并,类必须定义在命名空间之前。
class User {
constructor(public name: string) {}
}
namespace User {
export function create(name: string): User {
return new User(name)
}
}
const user = User.create("张三")
console.log(user.name)
合并后类有静态方法 create。
命名空间可以与函数合并。
function greet(name: string): string {
return `你好,${name}`
}
namespace greet {
export function formal(name: string): string {
return `尊敬的 ${name},您好`
}
}
console.log(greet("张三"))
console.log(greet.formal("李四"))
合并后函数有静态方法 formal。
命名空间可以与枚举合并。
enum Status {
Active,
Inactive
}
namespace Status {
export function isActive(status: Status): boolean {
return status === Status.Active
}
}
console.log(Status.isActive(Status.Active))
console.log(Status.isActive(Status.Inactive))
合并后枚举有静态方法 isActive。
合并时,后面的声明优先级更高。
interface User {
name: string
}
interface User {
name: string
email: string
}
合并后的接口以后面的定义为准。
声明合并常用于扩展第三方库的类型。
interface Window {
myApp: {
version: string
}
}
window.myApp = {
version: "1.0.0"
}
console.log(window.myApp.version)
扩展 Window 接口添加自定义属性。
可以使用声明合并扩展模块。
import { User } from "./user"
declare module "./user" {
interface User {
age: number
}
}
const user: User = {
id: 1,
name: "张三",
email: "zhangsan@example.com",
age: 25
}
扩展后的 User 接口包含 age 属性。
声明合并将多个同名声明合并为一个定义。接口合并会合并所有成员,函数成员会形成重载。命名空间可以与类、函数、枚举合并。声明合并常用于扩展第三方库的类型。合理使用声明合并可以灵活地扩展类型定义。