TypeScript常见核心配置和JS转译工具对比
tsc --init生成配置文件。在配置文件中开启 "strict": true和 "esModuleInterop": true。开发时使用 tsc -w或配合构建工具(如 Vite/Webpack)自动运行。预构建主要针对依赖),不是业务源码。核心目标是把依赖整理成开发服务器更高效可用的形态,并减少首次加载成本。这一步在 Vite 中默认由 esbuild 承担。
TypeScript编译器常用命令和核心配置选项两部分。
常用命令速查
这些是你日常开发中最常敲的命令:
| 命令 | 含义与用途 |
|---|---|
tsc |
默认构建。自动寻找当前目录下的 tsconfig.json 文件并编译整个项目。 |
tsc -w |
监听模式。编译后会保持运行,一旦文件有改动,自动重新编译(开发时很有用)。 |
tsc --init |
初始化。在当前目录生成一个包含推荐设置的 tsconfig.json 文件。 |
tsc -p <路径> |
指定项目配置。-p / --project 指向某份 tsconfig.json 文件,或含有 tsconfig.json 的目录;编译范围由该配置里的 include / files 等决定,不是随便传一个源码目录。例如:tsc -p tsconfig.app.json、tsc -p packages/foo(该目录下需有 tsconfig.json)。 |
tsc -b |
构建模式。专为 monorepo/多项目场景设计,会按依赖顺序构建(先编译被依赖的,再编译依赖它的),并生成缓存加速下次构建。普通项目用 -b 和直接用 tsc 区别不大。 |
tsc --noEmit |
仅检查。不写任何产物:既不生成 .js,也不生成 .d.ts(终端里仍可能打印类型错误/告警)。若只要类型声明、不要 JS,用 tsc --emitDeclarationOnly(并开 declaration: true,或 -d)。 |
tsc --showConfig |
查看配置。打印最终解析后的配置信息,而不进行构建(用于排查配置问题)。 |
tsc -v |
查看版本。显示当前 TypeScript 的版本号。 |
tsconfig 里 files 和 include 会冲突吗?
不冲突,是优先级关系:
| 配置 | 作用 |
|---|---|
files |
显式列出根文件;若写了此项,官方语义下 include / exclude 会被忽略。 |
include |
用通配符(如 src/**/*)决定进哪些文件;未写 files 时才按它与 exclude 生效。 |
exclude |
从 include 结果里再排除;若只用了 files,一般不参与。 |
实务上:要么只用 include(+ 可选 exclude),要么只用 files 做白名单,避免混写后误以为 include 仍在生效。
核心配置选项
这些选项通常写在 tsconfig.json 中,或者作为参数跟在命令后面:
语言环境设置
-
--target(或-t): 指定编译后的 JavaScript 版本。- 常见值:
es5,es6(或es2015),esnext。
含义:指定编译后的 JavaScript 代码要兼容哪种 ES 版本。例如设为
es5,会把const/let转成var,箭头函数转成普通函数。设为es6则保留新语法。与 Babel/SWC/esbuild 的差异:
tsc --target属于 TypeScript 编译阶段的“语言级降级”(按目标 ES 版本转换语法)。Babel/SWC/esbuild 通常在工程构建链路中负责面向目标运行环境的最终兼容转换,并可通过插件做更细粒度处理。- 一句话区分:
tsc关注“TS 代码如何编译成目标 JS 语法”;Babel/SWC/esbuild 关注“最终产物如何兼容目标环境(不同浏览器兼容性等)并接入构建能力”。
- 常见值:
-
--module(或-m): 指定使用哪种模块系统。- 常见值:
commonjs,esnext,node16。 - 作用:决定 TypeScript 输出后的 JS 采用哪种模块组织方式(例如保留 ESM,或转换为 CommonJS 风格)。
- 常见场景:
commonjs:偏传统 Node.js 生态,输出更接近require/module.exports语义。esnext:前端工程常用,保留import/export交给 Vite/Rollup/Webpack 做后续处理。node16:按 Node 16+ 的模块解析规则工作,适合现代 Node 服务端项目。
- 选择建议:前端(Vite)通常用
esnext;Node 后端按运行环境选node16或commonjs。
- 常见值:
-
--lib: 指定要包含的库文件(定义全局变量如window,document等)。- 常见值:
dom,es2015,esnext。 - 作用:决定 TypeScript 在类型检查时“认为你的运行环境有哪些内置 API”。
- 关键区别:
esnext:JavaScript 标准库类型(Promise、新数组方法等),不包含浏览器对象。dom:浏览器环境 API 类型(window、document、HTMLElement等)。dom.iterable:给部分 DOM 集合补充可迭代类型(可for...of、Array.from)。
- 容易混淆的点:
esnext不包含dom,它们是可组合关系,不是包含关系。 - 选择建议:
- 前端项目常见:
["ESNext", "DOM", "DOM.Iterable"]。 - Node 项目常见:
["ESNext"](再结合@types/node)。
- 前端项目常见:
- 常见值:
输出与文件处理
--outDir: 指定输出文件的目录(例如dist或build)。--declaration(或-d): 是否生成.d.ts类型声明文件(写库的时候必开)。--sourceMap: 是否生成.map文件(用于调试,让你能在浏览器里调试 TS 源码)。--jsx: 如何处理 JSX 语法。- 常见值:
react(生成React.createElement),react-jsx(React 17+ 新语法),preserve(保留不动,交给 Vite/Rollup 处理)。 - Vite + React 项目常见做法:使用
react-jsx,再由 Vite 插件链(Babel/SWC/esbuild)完成后续构建转换。 - 为什么“后面有 Babel/SWC 转 JSX”仍常保留
react-jsx:- TypeScript 即使
noEmit不产出 JS,也要做类型检查;jsx选项会影响 TS 对 JSX 的类型语义理解。 - Babel/SWC/esbuild 对 JSX 的处理属于构建转换阶段,与 TS 的类型语义检查不是同一层。
- 可记忆为:TS 的
jsx负责“按哪种 React JSX 语义做检查”;Babel/SWC 的 JSX 转换负责“把源码转成可运行代码”。
- TypeScript 即使
- 常见值:
严格程度与兼容性
-
--strict: 开启所有严格检查。- 建议:生产项目务必开启,它能帮你避免很多
undefined is not an object的运行时错误。
- 建议:生产项目务必开启,它能帮你避免很多
-
--allowJs: 允许编译 JavaScript 文件(即允许项目中混用.js和.ts)。 -
--esModuleInterop: 让import X from 'xxx'语法能正常工作于 CommonJS 模块。背景:npm 上很多老库(如 lodash、moment)是用
module.exports = xxx(即 CommonJS)写的,它们没有"默认导出"的概念。而你写的import _ from 'lodash'需要默认导出。没有这个参数时,导入的_可能是空的。加上它之后,TypeScript 会自动处理这个差异。
📌 总结建议
如果你刚开始配置项目,最核心的命令通常是:
tsc --init生成配置文件。- 在配置文件中开启
"strict": true和"esModuleInterop": true。 - 开发时使用
tsc -w或配合构建工具(如 Vite/Webpack)自动运行。
JavaScript 转译工具对比
一句话总览
- Babel / SWC / esbuild 主要解决“代码如何被转换”;
- Vite / Rollup / Webpack 主要解决“工程如何被构建与输出”。
工具概览
| 工具 | 开发公司 | 语言 | 速度 | 用途 |
|---|---|---|---|---|
| Babel | 社区开源 | JavaScript | 慢(基准) | 转译 JS/TS/JSX,插件生态最全 |
| SWC | Vercel/SWC团队 | Rust | 快 ~20x | Babel 替代品,兼容大部分插件 |
| esbuild | Figma (Evan Wallace) | Go | 最快 ~100x | 打包/压缩/依赖预构建 |
工具定位(先看这个)
| 工具 | 核心定位 | 在 Vite 中的常见角色 |
|---|---|---|
| Babel | 转译能力最灵活,插件生态最强 | 通过 @vitejs/plugin-react 参与 JSX/TSX 转译与插件扩展 |
| SWC | Rust 实现的高性能转译器 | 通过 @vitejs/plugin-react-swc 承担 React/TS 转译 |
| esbuild | 超快的转换/打包/压缩工具 | 开发时做依赖预构建;生产常用于 JS 压缩 |
说明:三者互为竞争关系,目标一致(转译 JS),但速度、定位、生态不同。
与 Vite / Rollup / Webpack 的关系
Vite / Rollup / Webpack是工程级构建器(模块图、代码拆分、资源处理、输出产物)。Babel / SWC / esbuild常作为其内部环节(转译、压缩、预构建等)被调用。
Vite 流程拆解(最容易混淆)
| 阶段 | 发生在什么命令 | 主要做什么 | 常见工具 |
|---|---|---|---|
| 依赖预构建 | vite dev |
预处理 node_modules,提升冷启动和请求效率 |
esbuild |
| HMR | vite dev |
模块热更新与状态保留 | Vite HMR 机制 + React Refresh |
| 应用源码转译 | vite dev 和 vite build |
处理业务源码中的 TS/JSX/语法转换 | Babel / SWC / esbuild(取决于插件与配置) |
| 最终打包输出 | vite build |
产出 dist、代码拆分、Tree-shaking |
Rollup(主)+ esbuild(常用于压缩) |
什么是预构建(Pre-bundling)
- 预构建主要针对 依赖(
node_modules),不是业务源码。 - 核心目标是把依赖整理成开发服务器更高效可用的形态,并减少首次加载成本。
- 这一步在 Vite 中默认由 esbuild 承担。
选型建议
- 需要复杂插件生态、定制转换规则:优先 Babel。
- 追求高性能且需求相对标准:优先 SWC 或 esbuild。
- Vite 项目默认先用官方推荐配置,只有在性能或插件诉求明确时再切换方案。
常见问题
Q: @babel/preset-typescript 和 tsc 的区别?
tsc:类型检查 +编译输出(可选)。@babel/preset-typescript:只移除类型并转译,不做类型检查。- 简单理解:TypeScript 类型注解(如
name: string、返回值: string)主要服务于开发期提示与校验;转译到 JavaScript 时会被移除,运行时并不保留这些类型信息。 - 示例:
// TypeScript(带类型注解) function greet(name: string): string { return name.toUpperCase() }// 转译后 JavaScript(类型被移除) function greet(name) { return name.toUpperCase() }
- 简单理解:TypeScript 类型注解(如
Q: 已经有 tsc,为什么还会用 Babel/SWC?
- 常见分工是:
tsc --noEmit负责类型检查,Babel/SWC/esbuild 负责构建链路内的代码转换。 - 补充:
tsc --noEmit很常见,但这不等于“必须使用@babel/preset-typescript”。- 只有当 Babel 直接处理
.ts/.tsx源码 时,通常才需要@babel/preset-typescript。 - 如果转译由 esbuild/SWC/Vite 内置链路 完成,通常不需要该 preset。
- 可以分两种模式理解:
- 模式 A:先
tsc产出 JS,再让 Babel 处理 JS。这种情况下通常不需要@babel/preset-typescript(因为 Babel 已经看不到 TS 类型语法)。 - 模式 B(推荐):
tsc只做类型检查(--noEmit),Babel 直接处理.ts/.tsx源码。这时通常需要@babel/preset-typescript,否则 Babel 默认无法识别类型注解。
- 模式 A:先
- 只有当 Babel 直接处理
TypeScript + Vite 推荐实践
- 开发:
vite(快速启动与 HMR)。 - 类型检查:
tsc --noEmit(只检查,不产出 JS)。 - 生产构建:
vite build(打包与产物输出)。
可参考的脚本拆分:
{
"scripts": {
"dev": "vite",
"typecheck": "tsc --noEmit",
"build": "vite build",
"build:check": "tsc --noEmit && vite build"
}
}
Q: Vite 内置的是 esbuild 还是 SWC?
- Vite 内置 esbuild(依赖预构建、压缩等)。
- SWC 需要额外安装对应插件(如
@vitejs/plugin-react-swc)。
Q: 为什么 tsc 没有输出?(Project References 问题排查)
执行 tsc 时没有任何类型错误输出,可能是因为项目使用了 Project References。
典型场景:根目录 tsconfig.json 使用了以下模式:
{
"files": [],
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
]
}
问题分析:
"files": []明确声明"当前配置不包含任何源文件""references"声明依赖的子项目- 直接运行
tsc --noEmit时,TypeScript 加载根配置,发现files为空就静默退出了
解决方案:
| 命令 | 说明 |
|---|---|
tsc -b |
构建所有引用项目(推荐,package.json 的 build 脚本常用) |
tsc --noEmit -p tsconfig.app.json |
指定具体配置文件 |
tsc -b tsconfig.app.json |
只构建 app 子项目 |
Q: @rollup/plugin-typescript 和 @rollup/plugin-babel + @babel/preset-typescript 能力对比?
| 能力 | @rollup/plugin-typescript |
@rollup/plugin-babel + @babel/preset-typescript |
|---|---|---|
| TS → JS 转换 | ✅ | ✅ |
| 类型检查 | ✅ | ❌ |
| 生成 .d.ts | ✅ | ❌ |
| 速度 | 较慢(tsc) | 快(Babel) |
关系总结:
@rollup/plugin-babel是桥梁,把 Babel 接入 Rollup@babel/preset-typescript是 Babel 的 TS 插件,移除 TS 类型注解- 两者是上下游关系:plugin 调用 preset
Q: Rolldown 是什么?现在成熟吗?
Rolldown 是一个用 Rust 编写的高性能 JavaScript/TypeScript 打包工具(Bundler)。
简单来说,你可以把它看作是 Rollup 的 Rust 版本。它的核心目标是提供与 Rollup 完全兼容的 API 和插件接口,但利用 Rust 的性能优势,实现比现有 JavaScript 打包工具(如 Webpack、Rollup、甚至 Vite 的默认构建)快得多的构建速度。但目前并不成熟。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐
所有评论(0)