Skip to content

TypeScript 中的模块

在TypeScript中编写基于模块的代码时,有三个主要方面需要考虑:

  • 语法:我想用什么语法来导入和导出东西?
  • 模块解析:模块名称(或路径)和磁盘上的文件之间是什么关系?
  • 模块输出目标:我编译出来的JavaScript模块应该是什么样子的?

ES模块语法

一个文件可以通过 export default 声明一个主要出口:

typescript
// @filename: hello.ts 
export default function helloWorld() { 
  console.log("Hello, world!"); 
}

然后通过以下方式导入:

typescript
import hello from "./hello.js"; 
hello();

除了默认的导出,你还可以通过省略 default 的 export ,实现有一个以上的变量和函数的导出。

typescript
// @filename: maths.ts 
export var pi = 3.14; 
export let squareTwo = 1.41; 
export const phi = 1.61;
export class RandomNumberGenerator {} 
export function absolute(num: number) { 
  if (num < 0) return num * -1; 
  return num; 
}

这些可以通过 import 语法在另一个文件中使用:

typescript
import { pi, phi, absolute } from "./maths.js"; 
console.log(pi); 

// const absPhi: number 
const absPhi = absolute(phi);

额外的导入语法

可以使用 import {old as new} 这样的格式来重命名一个导入:

typescript
import { pi as π } from "./maths.js"; 
// (alias) 
var π: number 
// import π 
console.log(π);

你可以将上述语法混合并匹配到一个单一的 import 中:

typescript
// @filename: maths.ts 
export const pi = 3.14; 
export default class RandomNumberGenerator {} 

// @filename: app.ts 
import RNGen, { pi as π } from "./maths.js"; 

// (alias) class RNGen 
// import RNGen 
RNGen; 

// (alias) const π: 3.14 
// import π 
console.log(π);

你可以把所有导出的对象,用 * as name ,把它们放到一个命名空间:

typescript
// @filename: app.ts 
import * as math from "./maths.js"; 

console.log(math.pi); 
// const positivePhi: number 
const positivePhi = math.absolute(math.phi);

你可以通过 import "./file " 导入一个文件,而不把任何变量纳入你的当前模块:

typescript
// @filename: app.ts 
import "./maths.js"; 

console.log("3.14");

在这种情况下, import 没有任何作用。然而, maths.ts 中的所有代码都被解析了,这可能引发影响其他对象的副作用。

typescript特定的ES模块语法

类型可以使用与JavaScript值相同的语法进行导出和导入。

typeScript
// @filename: animal.ts 
export type Cat = { breed: string; yearOfBirth: number }; 

export interface Dog { 
  breeds: string[]; 
  yearOfBirth: number; 
}

// @filename: app.ts 
import { Cat, Dog } from "./animal.js"; 
type Animals = Cat | Dog;

TypeScript用两个概念扩展了 import 语法,用于声明一个类型的导入。

  • import type

这是一个导入语句,只能导入类型:

typescript
// @filename: animal.ts 
export type Cat = { breed: string; yearOfBirth: number }; 
export type Dog = { breeds: string[]; yearOfBirth: number }; 
export const createCatName = () => "fluffy"; 

// @filename: valid.ts 
import type { Cat, Dog } from "./animal.js"; 
export type Animals = Cat | Dog; 

// @filename: app.ts 
import type { createCatName } from "./animal.js"; 
const name = createCatName();
  • 内联类型导入

TypeScript 4.5还允许以type为前缀的单个导入,以表明导入的引用是一个类型:

typescript
// @filename: app.ts 
import { createCatName, type Cat, type Dog } from "./animal.js"; 

export type Animals = Cat | Dog; 
const name = createCatName();

ES 模块语法与 CommonJS 行为

TypeScript 有 ES Module 语法,它直接与 CommonJS 和 AMD 的 require 相关联。使用 ES Module 的 import 在大多数情况下与这些环境的 require 相同,但这种语法确保你在 TypeScript 文件中与 CommonJS 的输出有1对1的匹配:

typescript
import fs = require("fs"); 
const code = fs.readFileSync("hello.ts", "utf8");