要点
TypeScript 工具链就三件事:装编译器(tsc)、决定怎么跑(tsx、ts-node 或 tsc 编译)、配检查工具(类型检查、测试、lint)。全局安装编译器是反模式,一切以项目锁文件为准。
概述
本章的产物是一个有 tsconfig、有锁文件、能独立运行类型检查、测试和 TS 源码的工程。编辑器扩展是辅助,不是项目能否构建的前提。文中版本事实以文末”版本核实”为准。
系统要求
| 组件 | 最低 | 推荐 | 说明 |
|---|---|---|---|
| Node.js | 20 | 22(当前活跃 LTS 线) | Node 运行时本身不能直接执行 .ts,跑 TS 需借助 tsx 等工具 |
| 编辑器 | 任意文本编辑器 | VS Code | 内置 TypeScript 语言服务,无需另装扩展 |
| 终端 | 支持 UTF-8 | 现代 Shell | 涉及中文输出时避免乱码 |
安装步骤
安装 Node.js
用版本管理器装,之后在多个项目间切换不痛苦:
# 用 nvm 安装当前 LTS 主版本
nvm install 22
nvm alias default 22
1. 验证;两个命令都有输出再往下走
node --version
npm --version
Windows 用 winget 安装对应主版本,macOS 用 Homebrew,装完同样跑上面两条验证命令。镜像加速按需配置:npm config set registry https://registry.npmmirror.com。
创建项目并安装 TypeScript
mkdir ts-demo && cd ts-demo
npm init -y
1. 项目本地安装,不钉版本号——装到的就是当前稳定版
npm install typescript
npx tsc --version
反模式:npm install -g typescript 全局安装。不同项目可能需要不同的编译器版本,全局只有一份时会互相打架;全局 tsc 还会让你误以为”项目在用这个版本”,实际编辑器和构建走的是各自路径。统一用项目本地安装加 npx,版本进锁文件,团队成员装出来的一致。
初始化 tsconfig
npx tsc --init
生成的 tsconfig.json 注释很全,关键项见下一节解释。此刻先确认一条:
# 能对(还不存在的)源码目录做检查,说明编译器装好了
npx tsc --noEmit
决定”怎么跑”:三条路
写好的 .ts 文件如何执行,是 TS 工具链里最容易绕晕的一步。Node 运行时目前还不能直接执行 .ts,需要借助工具。三条路的现状:
| 方式 | 原理 | 现状与适用 |
|---|---|---|
| tsx | esbuild 转译 | CommonJS 与 ESM 都处理,零配置上手,新项目直接运行的推荐选择 |
| ts-node | 运行时编译 | 老牌方案,处于维护状态,ESM 支持依赖 Node 的实验性 loader API;存量项目能跑就继续,新项目建议直接选 tsx |
| tsc 编译后运行 | 先编译成 JS 再 node 执行 | 不引入任何运行时依赖,产物可直接部署,适合发布环境与对产物有要求的场景 |
# 选 tsx:开发依赖即可
npm install -D tsx
npx tsx src/main.ts
反模式:新项目选 ts-node 起步。它的 ESM 兼容问题是历史包袱,社区共识已迁向 tsx;网上大量旧教程默认 ts-node,看发布日期再信。
测试与静态检查
# 测试框架 Vitest,当前 2.x 大版本
npm install -D vitest
npx vitest run
lint 需要时加 typescript-eslint(含 parser 与插件),按官方安装指引来;格式化交给 Prettier,两者职责不重叠。VS Code 用户在命令面板执行”TypeScript: Select TypeScript Version”选”Use Workspace Version”,保证编辑器红线与项目编译器同一版本——编辑器内置版本与项目版本不一致时,同一个文件两边报错不同,是新手最常见的困惑来源。
配置文件
tsconfig.json
{
"compilerOptions": {
"target": "es2022",
"module": "nodenext",
"moduleResolution": "nodenext",
"strict": true,
"noEmit": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src"]
}
逐项说为什么:strict 打开全家桶严格检查(严格空值检查是其中价值最大的一项),默认开,别关;noEmit 让 tsc 只做类型检查不产出 JS——运行交给 tsx,检查与转译分离,职责更清楚,需要编译产物时删掉这行再配 outDir;module/moduleResolution 用 nodenext 与 Node 的真实解析规则对齐,省掉一堆”本地能跑打包报错”的坑;skipLibCheck 跳过依赖包内部类型检查,只查你的代码,速度快得多。
package.json 的 scripts
{
"scripts": {
"type-check": "tsc --noEmit",
"start": "tsx src/main.ts",
"test": "vitest run"
}
}
三条命令就是日常全部:type-check 管类型,start 管运行,test 管行为。注意 tsx 只负责转译运行、不做类型检查——”代码跑起来了”不代表”类型没问题”,两条命令都要跑。
开发工作流程
| 时机 | 命令 | 看什么 |
|---|---|---|
| 保存文件时 | (编辑器自动) | 红线与快速修复 |
| 提交前 | npm run type-check && npm run test | 零错误再提交 |
| 运行调试 | npm run start | stdout/stderr 与退出码 |
| 依赖变动后 | npm ci | 按锁文件原样安装,复现环境 |
常见问题
node src/main.ts 报 Unknown file extension “.ts”
Node 只能执行 JS,不认识 .ts 扩展名,这个报错是必然的。用 npx tsx src/main.ts 直接跑;或者先 npx tsc 编译成 JS,再用 node 运行产物。
strict 模式报错一大片,能不能关掉
反模式:关 strict 换清净。严格模式的报错就是类型系统在提前还债——空值问题在编译期暴露好过运行时炸在生产。正确姿势是逐条修,报错信息里”可能在为 undefined”那行就是修法提示。
import 报 Cannot find module,本地文件明明在
多半是 ESM/CJS 混用:package.json 有 "type": "module" 时,相对导入必须写全扩展名(./util.js 而非 ./util);没有该字段则项目按 CJS 解析。module 配置、package.json type、导入写法三者要对齐。
最佳实践
环境搭好的验收标准是:从干净目录 npm install && npm run type-check && npm run test 全绿。锁文件必须提交,升级 TypeScript 与升级依赖一样是显式任务,看官方发布说明再动。编译器、运行器、测试器三者版本都以锁文件为准,文档教程里的版本号过目即忘即可,别抄进项目。
快速检查清单
- Node 主版本就位,node/npm 命令可用
- TypeScript 项目本地安装,npx tsc –version 有输出
- tsconfig 开启 strict,include 圈定 src
- 运行方式已定(tsx / ts-node / tsc 编译),npm run start 可跑
- type-check 与 test 两条命令独立可用
- 锁文件已提交,干净目录可复现安装
延伸阅读
环境就绪后,下一篇《第一个 TypeScript 应用》从零写一个能跑的小 CLI,并把类型检查的即时收益演示给你看;已有内容里,《Next.js 与 TypeScript》讲框架场景下的类型边界,《Next.js 环境搭建与工具链》与本章同结构,Node 与包管理器细节更全。
版本核实(2025-02-01 撰写时检索):TypeScript 当前稳定版为 5.7.x(2024-11 发布);Node.js 当前活跃 LTS 为 22(22.12+);Vitest 当前 2.x;ts-node 处于维护状态。安装命令一律不钉版本号,具体版本以官方文档与你的锁文件为准。