命名空间

命名空间是 TypeScript 组织代码的一种方式,用于避免全局变量污染。命名空间将相关的代码组织在一起,提供命名隔离。现代开发中推荐使用模块代替命名空间。

基本语法

使用 namespace 关键字定义命名空间。

namespace Utils {
  export function formatDate(date: Date): string {
    return date.toLocaleDateString("zh-CN")
  }

  export function formatCurrency(amount: number): string {
    return ${amount.toFixed(2)}`
  }
}

console.log(Utils.formatDate(new Date()))
console.log(Utils.formatCurrency(99.99))

export 关键字将成员暴露给命名空间外部使用。

嵌套命名空间

命名空间可以嵌套。

namespace App {
  export namespace Models {
    export interface User {
      id: number
      name: string
    }
  }

  export namespace Services {
    export function fetchUser(id: number): Models.User {
      return { id, name: "张三" }
    }
  }
}

const user = App.Services.fetchUser(1)
console.log(user.name)

嵌套命名空间可以更好地组织代码结构。

跨文件命名空间

命名空间可以跨多个文件。

export namespace App {
  export interface User {
    id: number
    name: string
  }
}

另一个文件扩展命名空间。

export namespace App {
  export interface Product {
    id: number
    name: string
    price: number
  }
}

使用时导入命名空间。

import { App } from "./app"

const user: App.User = { id: 1, name: "张三" }
const product: App.Product = { id: 1, name: "商品", price: 99.99 }

别名

可以使用别名简化命名空间访问。

namespace App {
  export namespace Models {
    export interface User {
      id: number
      name: string
    }
  }
}

import Models = App.Models

const user: Models.User = { id: 1, name: "张三" }

别名让代码更加简洁。

命名空间与模块

命名空间和模块是不同的概念:

  • 命名空间:全局作用域,用于避免命名冲突
  • 模块:文件作用域,用于代码组织和复用

现代开发推荐使用模块代替命名空间。

export interface User {
  id: number
  name: string
}

export function fetchUser(id: number): User {
  return { id, name: "张三" }
}

模块提供更好的代码组织和复用能力。

何时使用命名空间

命名空间适用于以下场景:

  • 全局库的代码组织
  • 避免全局变量污染
  • 旧代码迁移

现代项目推荐使用模块。

命名空间的缺点

命名空间有一些缺点:

  • 全局作用域,可能导致命名冲突
  • 不利于代码分割和按需加载
  • 不利于 Tree Shaking
  • 调试困难

模块解决了这些问题,是现代开发的标准。

实际应用

命名空间常用于定义全局类型声明。

declare global {
  interface Window {
    myApp: {
      version: string
      config: Record<string, any>
    }
  }
}

window.myApp = {
  version: "1.0.0",
  config: {}
}

console.log(window.myApp.version)

全局声明扩展了全局对象的类型定义。

小结

命名空间使用 namespace 关键字定义,用于组织代码和避免全局变量污染。命名空间可以嵌套、跨文件,支持别名简化访问。现代开发推荐使用模块代替命名空间,模块提供更好的代码组织、复用和优化能力。命名空间适用于全局库和旧代码迁移场景。