在前面所有的学习中,我们都是通过一条简单的 “tsc test.ts” 命令,手动将一个独立的 TypeScript 文件编译成 JavaScript 来运行的。
但在真实的项目中(通常包含成百上千个文件),我们不可能每次都去手动输入一大堆带有复杂参数的编译命令(比如 tsc app.ts --target ES6 --strict true)。
我们更需要一个全局的 “指挥中心” 来统一管理整个项目的编译规则。这个指挥中心,就是大名鼎鼎的 tsconfig.json 文件。
TypeScript tsconfig.json 文件简介
如果想要在一个项目中初始化 TypeScript 的配置文件,我们只需要在项目根目录下,打开终端并执行以下命令即可:
tsc --init执行完毕之后,项目根目录下就会多出一个 tsconfig.json 文件(如下图所示)。

只要你的项目根目录包含了这个文件,就相当于告诉编辑器:这个项目是一个 TypeScript 项目,请 TypeScript 编译器在工作时,严格遵守这个文件里定义的规则。
接下来,当我们直接在终端输入 “tsc”(不需要加任何文件名)时,编译器就会自动读取该文件,并对整个项目进行全量编译。
打开生成的 tsconfig.json 文件,我们会发现里面全是配置项。我们先跳过最复杂的 compilerOptions,来看看在这个 JSON 文件的最外层(顶层),有哪几个决定文件命运的关键属性。
顶层文件的匹配规则:
{
"compilerOptions": {
// ...复杂的编译选项,稍后详讲
},
// include:需要编译哪些文件(支持 glob 匹配通配符)
"include": [
"src/**/*"
],
// exclude:不要编译哪些文件
"exclude": [
"node_modules",
"dist",
"**/*.spec.ts"
]
}"include" 选项用于告诉 TypeScript 需要编译哪些文件,其中 "src//*" 表示匹配 src 目录下的所有文件(递归查询)。
"exclude" 选项用于告诉 TypeScript 千万不要编译哪些文件。默认情况下,即便不显式写 exclude,TypeScript 也会非常聪明地自动帮我们排除掉 node_modules 目录。
tsconfig.json 文件中的 compilerOptions 对象
在 tsconfig.json 文件中,compilerOptions 是最核心、最庞大的对象,它直接决定了 TypeScript 的 “行为表现” 和 “输出产物”。
针对日常开发,可以分为以下 6 大核心的配置组。
1. 模块与产物 (target / module / outDir)
这一组配置决定了 TypeScript 代码编译成 JavaScript 后,到底长什么样子,以及存放在哪里。
{
"compilerOptions": {
// target: 指定编译后的 ECMAScript 目标版本。
// 为了兼容旧版浏览器,通常设为 "ES2015" (即 ES6) 或 "ES5"。
// 在现代打包工具(Vite)环境中,通常设为 "ESNext"(最新版)。
"target": "ES2015",
// module: 指定编译后代码使用的模块化标准。
// 开发 Node.js 应用通常用 "CommonJS";现代前端开发通常用 "ESNext"。
"module": "ESNext",
// outDir: 编译后的 JS 文件统一输出到哪个目录下。
"outDir": "./dist",
// rootDir: 指定 TS 源码的根目录,用于在 outDir 中维持原本的目录结构。
"rootDir": "./src"
}
}2. 路径别名 (baseUrl & paths)
如果小伙伴们已经接触过 Vue 或 React,那么肯定对下面这种高逼格的导入方式比较熟悉:
import UserCard from "@/components/UserCard"这里的 “@” 就是一个路径别名。像这种路径别名,如果我们不在 tsconfig.json 中显式配置它,那么 TypeScript 编译器就会立刻给你爆红,因为它根本不认识 “@” 是个什么。
{
"compilerOptions": {
// baseUrl: 解析非相对模块名的基准目录(通常设为 "." 代表项目根目录)
"baseUrl": ".",
// paths: 路径别名的核心映射表(必须配合 baseUrl 使用)
"paths": {
"@/*": ["src/*"],
"@utils/*": ["src/utils/*"]
}
}
}此外需要注意的是,这里配置的 paths 仅仅是让 TypeScript 的 “类型检查器” 不报错,并提供智能提示。但如果要让项目真正跑起来,我们还需要在打包工具(如Vite 的 resolve.alias 或 Webpack 的 alias)中配置完全一样的映射才行。
3. 类型安全(strict)
TypeScript 最强大的地方就在于它的 “严格检查”。官方提供了一个非常暴力的 “总闸”开关:strict。
{
"compilerOptions": {
// strict: 启用所有严格的类型检查选项。这通常是大厂和现代框架的强制要求!
"strict": true,
// --- 下面是 strict 为 true 时,底层自动开启的核心子选项(了解即可) ---
// 禁止隐式 any(如果 TS 猜不出类型,且你没写类型,直接报错拦截)
"noImplicitAny": true,
// 严格空值检查(上一章讲的 NonNullable 就是为了应对它。杜绝 null 导致的运行时崩溃)
"strictNullChecks": true
}
}4. 模块互操作性 (esModuleInterop)
在旧版的 CommonJS 生态(如老版本的 React 库)中,很多库使用的是 module.exports = React 导出的。而现代前端使用 ES Module 导入时,写的是 import React from "react"。
如果不做处理,TypeScript 会直接报错 “该模块没有默认导出”。为了让 CommonJS 和 ES Module 能够完美地 “交朋友”,我们必须开启这个选项:
{
"compilerOptions": {
// 允许以 ES Module 的 default 方式,去导入 CommonJS 的模块
"esModuleInterop": true
}
}5. 运行环境库 (lib)
TypeScript 编译器默认只认识最基础的 JavaScript 语法。如果你在代码里写了 document.getElementById("app"),TypeScript 可能会直接报错,因为它不知道 document 是个什么东西(毕竟在纯 Node.js 环境里是没有 DOM 概念的)。
通过配置 lib,我们可以明确告诉 TypeScript 编译器:“我的代码将来是在浏览器里跑的,请把浏览器的 DOM API 也加入到你的类型字典里!”
{
"compilerOptions": {
// 引入最新 ES 语法特性,以及浏览器的 DOM/BOM API 提示
"lib": ["ESNext", "DOM", "DOM.Iterable"]
}
}6. 跳过第三方库检查 (skipLibCheck)
这是企业级开发中必须开启的救命选项!
很多时候,我们满心欢喜地通过 npm 安装了一个第三方开源库。结果一编译,满屏全是从 node_modules 里面冒出来的红色类型报错。这根本不是我们业务代码的问题,却卡住了我们打包的进度,让人非常崩溃。
{
"compilerOptions": {
// 忽略所有 .d.ts 声明文件的类型检查(尤其是 node_modules 里的)
// 极大地提升编译速度,并彻底消除第三方库导致的报错
"skipLibCheck": true
}
}TypeScript 企业级完整配置模板
为了方便小伙伴们在实际项目中直接抄作业,我们准备了一份现代前端(Vue / React + Vite)最标准的 tsconfig.json 配置骨架,小伙伴们之间复制过去就能使用。
完整的 tsconfig.json:
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
// 现代前端(Vite/打包工具)的标准模块解析策略
"moduleResolution": "bundler",
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"skipLibCheck": true,
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"exclude": ["node_modules", "dist"]
}此外还需要提一下的是,在一些庞大的 Monorepo(单体多仓库)企业级架构中,如果有多个子项目,每个项目都写一份长长的 tsconfig.json 会非常冗余。
实际上,TypeScript 贴心地为我们提供了 extends 属性,允许我们抽离出一份基础配置,然后在子项目中 “继承” 并覆盖它,比如:
{
// 继承项目根目录下的基础配置
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "./dist" // 覆盖特定的输出目录
}
}