TypeScript$File-Module

81 阅读2分钟

TypeScript$File-Module

P. JavaScript Module

JavaScript 模块的标准是 ES Module,使用的是 import / export 语法。

在 ES Module 出现之前,Node 的标准是 CommonJS,使用的是 require / module.exports 语法。

0. Module or not

在 TypeScript 看来,没有使用 import / export / top-level await 的文件是 script,不是 module。

如果想让一个文件变成 module,可以加一行 export {}

1. ES Module imports and exports of TypeScript

1.1 import

JavaScript 的 import 语法就不说明了,TypeScript 特有的语法:

  • normal import:import { Cat, Dog } from "./animal.js"; // Cat and Dog are types
  • import type:import type { Cat, Dog } from "./animal.js";
  • inline type imports:import { createCatName, type Cat, type Dog } from "./animal.js";

1.2 export

// @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;

2. CommonJS Interop

CommonJS 的导出分为两种情况:

  1. 暴露出一个对象,每个属性都有明确的名字:module.exports = { Banana }
  2. 暴露对象的属性没有明确的名字:module.exports = Melon 对于第一种,正常的导入就行
import { Banana } from './banana'

const fs = require("fs")
import * as fs from "fs"
import { readFileSync } from "fs"

对于第二种情况,正常的导入会报错,需要使用 TypeScript 的特殊语法(配置项esModuleInterop 和 allowSyntheticDefaultImports 能阻止报错,但其他引入你的 TypeScript 项目也得开启这两个配置项):

import * as Melon from "./melon" // error
import Melon = require("./melon") // OK

3. Native ES module support

This means you can natively run code containing thing like import { Foo } from 'bar', use top-level await and more!

通过文件名的后缀能区分 native ES modules / CJS modules:

  • Files with the .mjs extension are treated as native ES modules
  • Files with the .cjs extension are treated as CJS modules

区分普通的 .js 文件是什么类型——配置 package.json"type"

  • "module" : ES modules
  • "commonjs": CommonJS

3.1 TypeScript ES modules

  • .mts files are for TypeScript ES modules, and generate ES modules as output
  • .cts files are for TypeScript CJS modules, and generate CJS modules as output

4. Importing non-TS things

import img from "./file.png"
// error. Cannot find module './file.png' or its corresponding type declarations.

file.png is obviously not a TypeScript file — we just need to tell TypeScript that whenever we import a .png file, it should be treated as if it’s a JS module with a string value as its default export.

This can be accomplished through a module declaration as shown below:

// @filename: global.d.ts
declare module "*.png" {
  const imgUrl: string
  export default imgUrl
}
// @filename: component.ts
import img from "./file.png"

Links

MDN_JavaScript_Module

TypeScriptModule

CourseTypeScriptModule