Skip to content

Typescript 声明文件与模块 ​

声明文件 ​

当引入的库没有类型声明时,需要手动编写 .d.ts 文件。可以在 tsconfig.json 中通过 include 指定声明文件路径:

json
{
  "include": ["./src/**/*.ts", "./src/**/*.d.ts"]
}
{
  "include": ["./src/**/*.ts", "./src/**/*.d.ts"]
}

声明文件使用 declare 关键字。

查找声明文件 ​

  1. 检查库自身是否包含 .d.ts 文件
  2. 查找社区声明文件:npm install @types/库名 -D
  3. 如果都没有,手动编写声明文件

全局库 ​

定义在 document 或 window 上的方法:

ts
// global.d.ts
declare function getTitle(): string
// global.d.ts
declare function getTitle(): string

模块化库 ​

使用 import/require 的都是模块化库。

UMD 库 ​

既可全局使用也可模块导入:

ts
// moment 是典型的 UMD 库
import moment from 'moment'
// moment 是典型的 UMD 库
import moment from 'moment'

修改全局模块 ​

当在原型上添加方法时:

ts
// 源文件
String.prototype.getFirstLetter = function () {
  return this[0]
}

// 声明文件(利用声明合并)
interface String {
  getFirstLetter(): string
}
// 源文件
String.prototype.getFirstLetter = function () {
  return this[0]
}

// 声明文件(利用声明合并)
interface String {
  getFirstLetter(): string
}

依赖声明 ​

依赖全局库:

ts
/// <reference types='moment'/>
/// <reference types='moment'/>

依赖模块:

ts
import * as moment from 'moment'
import * as moment from 'moment'

快捷外部模块声明 ​

快速为模块添加声明:

ts
// typings/moment/index.d.ts
declare module 'moment'
// typings/moment/index.d.ts
declare module 'moment'

模块解析 ​

通过 tsconfig.json 的 moduleResolution 设置,两种策略:

Classic 策略 ​

查找 .ts 文件 → .d.ts 文件 → 向上一级继续查找。

Node 策略 ​

模拟 Node.js 模块解析:.ts → .tsx → .d.ts,查找 package.json 中 types → main 字段。

解析配置项 ​

json
{
  "compilerOptions": {
    "baseUrl": ".",                        // 基目录
    "paths": {                             // 路径映射
      "*": ["node_modules/@types", "src/typings"]
    },
    "rootDirs": ["src/modules", "src/ts-modules"]  // 虚拟目录合并
  }
}
{
  "compilerOptions": {
    "baseUrl": ".",                        // 基目录
    "paths": {                             // 路径映射
      "*": ["node_modules/@types", "src/typings"]
    },
    "rootDirs": ["src/modules", "src/ts-modules"]  // 虚拟目录合并
  }
}

命名空间 ​

使用 namespace 定义,内部通过 export 导出:

ts
namespace Validation {
  const isLetterReg = /^[A-Za-z]+$/
  export const isNumber = /^[0-9]+$/
  export const checkLetter = (val: string) => isLetterReg.test(val)
}

// 使用
/// <reference path='./a.ts'/>
Validation.checkLetter('abc')
namespace Validation {
  const isLetterReg = /^[A-Za-z]+$/
  export const isNumber = /^[0-9]+$/
  export const checkLetter = (val: string) => isLetterReg.test(val)
}

// 使用
/// <reference path='./a.ts'/>
Validation.checkLetter('abc')

建议:命名空间能实现的 import 都能实现,优先使用 import。

命名空间别名 ​

ts
namespace Shape {
  export namespace Polygons {
    export class Trggler {}
  }
}
import polygons = Shape.Polygons
let trggler = new polygons.Trggler()
namespace Shape {
  export namespace Polygons {
    export class Trggler {}
  }
}
import polygons = Shape.Polygons
let trggler = new polygons.Trggler()

声明合并 ​

同名声明会被合并为一个:

接口合并 ​

ts
interface Info { name: string }
interface Info { age: number }
// Info 同时有 name 和 age

// 非函数成员类型必须相同,函数成员作为重载(后面的优先级更高)
interface Info { name: string }
interface Info { age: number }
// Info 同时有 name 和 age

// 非函数成员类型必须相同,函数成员作为重载(后面的优先级更高)

命名空间合并 ​

未 export 的属性在同名命名空间中无法访问:

ts
namespace Validate {
  const isLength = /^[0-9]+$/
  export const checkLength = () => {}
}
namespace Validate {
  // 取不到 isLength
  export const checkLetter = () => {}
}
namespace Validate {
  const isLength = /^[0-9]+$/
  export const checkLength = () => {}
}
namespace Validate {
  // 取不到 isLength
  export const checkLetter = () => {}
}

类 + 命名空间合并 ​

类必须在命名空间前面:

ts
class Validations {
  constructor() {}
  public checkType() {}
}
namespace Validations {
  export const numberReg = /^[0-9]+$/
}
class Validations {
  constructor() {}
  public checkType() {}
}
namespace Validations {
  export const numberReg = /^[0-9]+$/
}

函数 + 命名空间合并 ​

ts
function countUp() { countUp.count++ }
namespace countUp {
  export let count = 0
}
function countUp() { countUp.count++ }
namespace countUp {
  export let count = 0
}

枚举 + 命名空间合并 ​

ts
enum Colors { red, green, blue }
namespace Colors {
  export const yellow = 3
}
enum Colors { red, green, blue }
namespace Colors {
  export const yellow = 3
}

声明创建实体对照 ​

声明类型创建命名空间创建类型创建值
Namespace✓✓
Class✓✓
Enum✓✓
Interface✓
Type Alias✓
Function✓
Variable✓