TypeScript 配置详解
tsconfig.json 是 TypeScript 项目的配置文件,用于指定编译选项和项目设置。本章详细介绍常用配置选项及其作用。
基本结构
{
"compilerOptions": {
// 编译选项
},
"include": [
// 包含的文件
],
"exclude": [
// 排除的文件
],
"files": [
// 指定文件
],
"extends": [
// 继承的配置
],
"references": [
// 项目引用
]
}
编译目标与模块
target - 编译目标
指定编译后的 JavaScript 版本:
{
"compilerOptions": {
"target": "ES2020"
}
}
可选值:
"ES3"(默认):IE 兼容"ES5":广泛兼容"ES6"/"ES2015":现代浏览器"ES2017":支持 async/await"ES2020":支持可选链、空值合并"ES2022":支持顶层 await"ESNext":最新特性
示例对比:
// 源码
const obj = { a: 1, b: 2 };
const { a, ...rest } = obj;
编译为 ES5:
var __rest = function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
return t;
};
var obj = { a: 1, b: 2 };
var a = obj.a, rest = __rest(obj, ["a"]);
编译为 ES2018+:
const obj = { a: 1, b: 2 };
const { a, ...rest } = obj;
module - 模块系统
指定生成的模块代码格式:
{
"compilerOptions": {
"module": "ES2020"
}
}
可选值:
"CommonJS":Node.js 默认格式"AMD":RequireJS 等加载器"ES6"/"ES2015":ES Module"ES2020":ES Module + 动态导入"ES2022":ES Module + 顶层 await"UMD":通用模块定义"System":SystemJS"None":不生成模块
moduleResolution - 模块解析策略
{
"compilerOptions": {
"moduleResolution": "node"
}
}
可选值:
"node":Node.js 风格(推荐)"classic":旧版 TypeScript 风格"node16"/"nodenext":Node.js ESM 支持
lib - 包含的库类型定义
指定编译时可用的 API 类型:
{
"compilerOptions": {
"lib": ["ES2020", "DOM", "DOM.Iterable"]
}
}
常用组合:
- 浏览器项目:
["ES2020", "DOM", "DOM.Iterable"] - Node.js 项目:
["ES2020"](配合@types/node) - 纯 TypeScript:
["ES2020"]
严格模式
strict - 启用所有严格选项
{
"compilerOptions": {
"strict": true
}
}
启用 strict 相当于同时启用以下选项:
{
"compilerOptions": {
"strict": true,
// 以下选项自动启用
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictBindCallApply": true,
"strictPropertyInitialization": true,
"noImplicitThis": true,
"useUnknownInCatchVariables": true,
"alwaysStrict": true
}
}
strictNullChecks - 严格的 null 检查
{
"compilerOptions": {
"strictNullChecks": true
}
}
关闭时:
let name: string = null; // 不报错
开启后:
let name: string = null; // 错误:不能将 null 赋给 string
let name: string | null = null; // 正确
noImplicitAny - 禁止隐式 any
{
"compilerOptions": {
"noImplicitAny": true
}
}
关闭时:
function add(a, b) { // a, b 隐式为 any
return a + b;
}
开启后:
function add(a, b) { // 错误:参数隐式有 any 类型
return a + b;
}
// 必须显式声明类型
function add(a: number, b: number) {
return a + b;
}
strictPropertyInitialization - 严格属性初始化
{
"compilerOptions": {
"strictPropertyInitialization": true
}
}
class User {
name: string; // 错误:属性未初始化
constructor() {}
}
// 解决方案
class User {
name: string = "默认名称"; // 方式一:默认值
constructor(public age: number) {} // 方式二:参数属性
}
class User {
name!: string; // 方式三:断言赋值
}
输出配置
outDir - 输出目录
{
"compilerOptions": {
"outDir": "./dist"
}
}
rootDir - 源码根目录
{
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist"
}
}
outFile - 合并输出文件
仅在 module 为 AMD、System 或 None 时有效:
{
"compilerOptions": {
"module": "AMD",
"outFile": "./dist/bundle.js"
}
}
declaration - 生成声明文件
{
"compilerOptions": {
"declaration": true,
"declarationDir": "./dist/types"
}
}
sourceMap - 生成源映射
{
"compilerOptions": {
"sourceMap": true
}
}
生成的 .js.map 文件用于调试时映射回源码。
路径映射
baseUrl - 基础路径
{
"compilerOptions": {
"baseUrl": "./src"
}
}
// 相对于 baseUrl 解析
import { User } from "models/user";
paths - 路径别名
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@components/*": ["src/components/*"],
"@utils/*": ["src/utils/*"]
}
}
}
// 之前
import { Button } from "../../../components/Button";
// 使用别名
import { Button } from "@/components/Button";
import { formatDate } from "@utils/date";
rootDirs - 多个根目录
{
"compilerOptions": {
"rootDirs": ["src", "generated"]
}
}
类型检查增强
noUnusedLocals - 检查未使用的局部变量
{
"compilerOptions": {
"noUnusedLocals": true
}
}
function example() {
const unused = 123; // 错误:未使用
return 456;
}
noUnusedParameters - 检查未使用的参数
{
"compilerOptions": {
"noUnusedParameters": true
}
}
function example(used: number, unused: string) { // unused 未使用
return used;
}
// 使用下划线前缀忽略
function example(used: number, _unused: string) {
return used;
}
noImplicitReturns - 检查隐式返回
{
"compilerOptions": {
"noImplicitReturns": true
}
}
// 错误:不是所有路径都返回值
function getColor(color: string) {
if (color === "red") {
return "#ff0000";
}
// 缺少 return
}
noFallthroughCasesInSwitch - 检查 switch 穿透
{
"compilerOptions": {
"noFallthroughCasesInSwitch": true
}
}
switch (value) {
case 1:
console.log("one");
// 错误:缺少 break,会穿透
case 2:
console.log("two");
break;
}
exactOptionalPropertyTypes - 精确的可选属性类型
{
"compilerOptions": {
"exactOptionalPropertyTypes": true
}
}
interface Config {
timeout?: number;
}
// 默认允许
const config: Config = { timeout: undefined };
// 启用后不允许
const config: Config = { timeout: undefined }; // 错误
JSX 支持
jsx - JSX 编译
{
"compilerOptions": {
"jsx": "react-jsx"
}
}
可选值:
"preserve":保留 JSX,输出.jsx文件"react":转换为React.createElement"react-jsx":转换为_jsx(React 17+)"react-jsxdev":开发模式下的react-jsx"vue":Vue 3 JSX 支持
// 源码
const element = <div className="test">Hello</div>;
// react 输出
const element = React.createElement("div", { className: "test" }, "Hello");
// react-jsx 输出
import { jsx as _jsx } from "react/jsx-runtime";
const element = _jsx("div", { className: "test", children: "Hello" });
jsxFactory - 自定义 JSX 工厂函数
{
"compilerOptions": {
"jsx": "react",
"jsxFactory": "h"
}
}
// 输出使用 h 而不是 React.createElement
const element = h("div", null, "Hello");
互操作性
esModuleInterop - ES 模块互操作
{
"compilerOptions": {
"esModuleInterop": true
}
}
启用后可以更方便地导入 CommonJS 模块:
// 关闭时需要
import * as React from "react";
// 开启后可以直接默认导入
import React from "react";
allowSyntheticDefaultImports - 允许合成默认导入
{
"compilerOptions": {
"allowSyntheticDefaultImports": true
}
}
允许从没有默认导出的模块中默认导入:
import moment from "moment"; // 即使 moment 没有 default 导出
resolveJsonModule - 解析 JSON 模块
{
"compilerOptions": {
"resolveJsonModule": true
}
}
import config from "./config.json";
console.log(config.version);
allowJs - 允许 JavaScript 文件
{
"compilerOptions": {
"allowJs": true
}
}
允许 .js 文件被导入和检查:
// 可以导入 .js 文件
import { helper } from "./utils.js";
checkJs - 检查 JavaScript 文件
{
"compilerOptions": {
"allowJs": true,
"checkJs": true
}
}
对 .js 文件也进行类型检查(需要 JSDoc 注释)。
项目引用
references - 项目引用
用于 monorepo 或多项目配置:
// tsconfig.json
{
"references": [
{ "path": "./shared" },
{ "path": "./frontend" },
{ "path": "./backend" }
]
}
// frontend/tsconfig.json
{
"compilerOptions": {
"composite": true, // 必须启用
"outDir": "./dist"
},
"references": [
{ "path": "../shared" }
]
}
composite - 复合项目
{
"compilerOptions": {
"composite": true,
"declaration": true, // 自动启用
"declarationMap": true
}
}
文件包含规则
include - 包含文件
{
"include": ["src/**/*", "tests/**/*"]
}
exclude - 排除文件
{
"include": ["src/**/*"],
"exclude": ["node_modules", "dist", "**/*.test.ts"]
}
files - 指定文件
{
"files": ["src/index.ts", "src/types.ts"]
}
继承配置
extends - 继承配置
// tsconfig.base.json
{
"compilerOptions": {
"strict": true,
"target": "ES2020",
"module": "ESNext"
}
}
// tsconfig.json
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"outDir": "./dist"
}
}
继承 npm 包的配置:
{
"extends": "@tsconfig/node18/tsconfig.json"
}
常用配置模板
Node.js 项目
{
"compilerOptions": {
"target": "ES2022",
"module": "CommonJS",
"lib": ["ES2022"],
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
React 项目
{
"compilerOptions": {
"target": "ES2020",
"lib": ["DOM", "DOM.Iterable", "ES2020"],
"module": "ESNext",
"jsx": "react-jsx",
"strict": true,
"moduleResolution": "node",
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true
},
"include": ["src"],
"exclude": ["node_modules"]
}
库开发
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"lib": ["ES2020"],
"declaration": true,
"declarationDir": "./dist/types",
"outDir": "./dist/esm",
"rootDir": "./src",
"strict": true,
"moduleResolution": "node",
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"composite": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist", "**/*.test.ts"]
}
Next.js 项目
{
"compilerOptions": {
"target": "ES2017",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}
小结
本章我们学习了 TypeScript 配置:
- 编译目标:
target和module选项 - 严格模式:
strict及相关选项 - 输出配置:
outDir、declaration等 - 路径映射:
baseUrl、paths别名配置 - 类型检查:
noUnusedLocals等增强检查 - JSX 支持:React、Vue 等框架配置
- 互操作性:CommonJS/ESModule 互操作
- 项目引用:monorepo 配置
- 配置模板:常用项目的配置示例
练习
- 创建一个 Node.js 项目的
tsconfig.json - 配置路径别名
@/*指向src/* - 启用所有严格模式选项,检查现有代码
- 创建一个支持 React 和 Node.js 的多项目配置