第三章 - 将模块编译为JavaScript

55 阅读2分钟

这是TypeScript Compiler API系列的第三篇文章

学习如何使用Compiler API将TypeScript转译为JavaScript

现在让我们开始探索真正的Compiler API吧💃!

如第1章所述,编译器API功能丰富,其中一项核心功能就是将TypeScript代码直接转译为JavaScript代码。本章将介绍如何通过API实现这一过程。

准备工作

首先在电脑上创建实验目录。确保已全局安装npm,然后执行命令:

  • mkdir ts-compiler-api-fun(创建目录)
  • cd ts-compiler-api-fun(进入目录)

Windows用户请注意命令差异。进入空目录后:

  1. 运行npm init初始化项目

  2. 安装依赖:

    • TypeScript:npm install typescript(或yarn add typescript
    • NodeJS类型定义:npm install --save-dev @types/node

代码转译

  1. 创建TypeScript文件:

    • 执行touch fun.ts
    • 用VSCode等编辑器打开:code fun.ts
  2. 编写基础TS代码:

function hello(world: string): boolean {
  return world === "world"
}
  1. 创建编译脚本文件index.mjs,内容如下:
import ts from "typescript"
import fs from "fs"
const source = fs.readFileSync("./fun.ts", { encoding: "utf8" })
const result = ts.transpileModule(source, {
  compilerOptions: { module: ts.ModuleKind.ESNext }
})
fs.writeFileSync("fun.js", result.outputText)
  1. package.jsonscripts中添加:

    "compile": "node index.mjs"
    
  2. 运行npm run compile后,将生成:

function hello(world) {
  return world === "world"
}

成功移除了类型注解!恭喜你首次直接使用Compiler API完成了编译🎉!

编译器选项

调用ts.transpileModule()时传入的compilerOptions参数至关重要。目前编译器提供100+个配置选项,这些选项与tsconfig.jsontsc命令行工具完全兼容。

完整选项列表参考TypeScript官方文档

使用ts.createProgram()

之前我们通过Node的fs模块处理文件,现在改用Compiler API自带的文件处理功能,这对大批量文件更高效。

基本用法:

const program = ts.createProgram(fileNames, compilerOptions)
const result = program.emit()

程序会自动生成对应的.js文件。

优化后的完整示例:

import ts from "typescript"
const program = ts.createProgram(["./fun.ts"], {
  module: ts.ModuleKind.ESNext
})
const result = program.emit()

代码更简洁,接下来我们看看如何获取诊断信息。

诊断信息

诊断信息能帮助开发者定位代码问题。让我们修改示例代码制造一个类型错误:

function hello(world: string): bolean {  // 故意拼错boolean
  return world === "world"
}

增强诊断信息输出:

// 合并编译前和编译后的诊断信息
const diagnostics = ts.getPreEmitDiagnostics(program).concat(result.diagnostics)
​
// 格式化输出
diagnostics.forEach((diagnostic) => {
  if (diagnostic.file) {
    const { line, character } = ts.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start)
    const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n")
    console.log(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`)
  } else {
    console.log(ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"))
  }
})

运行后将看到智能提示:

fun.ts (1,32): Cannot find name 'bolean'. Did you mean 'boolean'?

再测试noImplicitAny选项:

const program = ts.createProgram(["fun.ts"], {
  module: ts.ModuleKind.ESNext,
  noImplicitAny: true
})

当参数没有类型注解时,会提示:

fun.ts (1,16): Parameter 'world' implicitly has an 'any' type.

本章总结

本节我们学会了:

  1. 使用Compiler API转译TS代码
  2. 处理诊断信息
  3. 通过编译器选项控制代码检查

这些知识将为下一章的TypeScript代码解析打下基础。