learn-typescript

模块

导入具有副作用的模块

虽然不推荐,但是一些模块会设置一些全局变量供其他模块访问,这些模块的导入方法:

import './sideEffectModule.js'

export=和 import=语法

CommonJS 和 AMD 的默认导出不相互兼容,所以 TypeScript 用 export = 语法来支持这两种导出方式, 而相应的需要使用 import module = require('module)的语法来导入。

ZipCodeValidator.ts

let numberRegexp = /^[0-9]+$/
class ZipCodeValidator {
  isAcceptable(s: string) {
    return s.length === 5 && numberRegexp.test(s)
  }
}

export = ZipCodeValidator

TestZipCodeValidator.ts

import ZipCodeValidator = require('./ZipCodeValidator')

console.log(new ZipCodeValidator().isAcceptable('12345')) // true

外部模块

这里的外部模块,通常指的是 node 内置模块、AMD 模块系统下引入的全局库等。在 TypeScript 中使用这些库(模块)时,可以通过自己定义一个 .d.ts 声明文件来描述这些模块暴露的 API,例如:

node.d.ts(示例)

declare module 'url' {
  export interface Url {
    protocol?: string
    hostname?: string
    pathname?: string
  }

  export function parse(
    urlStr: string,
    parseQueryString?: boolean,
    slashesDenoteHost?: boolean
  ): Url
}

declare module 'path' {
  export function normalize(p: string): string
  export function join(...paths: any[]): string
  export let sep: string
}

现在就可以配合 三斜线指令 来使用这些模块了:

/// <reference path="node.d.ts"/>

import url from 'url'
let myUrl = url.parse('http://www.typescriptlang.org')

外部模块的简写

如果不想在使用外部模块之前花时间去编写声明文件,可以采用声明的简写形式以便立即使用该外部模块:

xxmodule.d.ts

declare module 'xxmodule'

此时,简写模块里所有导出的类型都将是 any

import x, { y } from 'xxmodule'
x(y)

注意: 声明 module 时模块名需要加上引号。

模块解析策略

共有两种模块解析策略: NodeClassic。使用 --moduleResolution 指定使用哪种策略。若未指定,那么使用 --module AMD | System | ES2015 时默认值为 Classic ,其他情况为 Node

Classic

Classic 以前是默认解析策略,现在存在的意义是为了向后兼容。

Node

Node 解析策略类似 Node.js 的解析策略来在编译阶段定位模块定义文件,在 Nodejs 解析逻辑基础上增加了 .ts , .tsx, .d.ts,同时在 package.json 中使用 types 字段指定入口文件的定义文件位置。

对于相对路径的引入 import { x } from 'module' ,查找顺序为:

  1. 先把 module 看作文件依次查找后缀: .ts -> .tsx -> .d.ts
  2. 再把 module 看作文件夹, 依次查找: module/package.json中types属性值 -> module/index.ts -> module/index.tsx -> module/index.d.ts

对于非相对路径,从当前文件夹向项目根目录依次查找 node_modules 目录,找到 node_modules 目录后,从该 node_modules 中按照上面相对路径的规则查找。