TypeScript 环境配置
本章将介绍如何安装和配置 TypeScript 开发环境。
安装 TypeScript
使用 npm 安装
# 全局安装
npm install -g typescript
# 验证安装
tsc --version
# Version 5.x.x
# 本地安装(推荐)
npm install --save-dev typescript
解释:推荐在项目中本地安装 TypeScript,这样可以确保团队成员使用相同的版本。
使用 npx 运行
# 使用 npx 运行本地安装的 tsc
npx tsc --version
第一个 TypeScript 程序
创建文件
创建 hello.ts 文件:
// hello.ts
function greet(name: string): string {
return `Hello, ${name}!`;
}
const message = greet("TypeScript");
console.log(message);
编译运行
# 编译 TypeScript 文件
tsc hello.ts
# 运行生成的 JavaScript 文件
node hello.js
// 输出:Hello, TypeScript!
解释:tsc 命令将 .ts 文件编译成 .js 文件。编译后的 JavaScript 文件可以在 Node.js 或浏览器中运行。
编译选项
# 指定输出目录
tsc hello.ts --outDir dist
# 指定目标版本
tsc hello.ts --target ES2020
# 监听文件变化
tsc hello.ts --watch
// 同时使用多个选项
tsc hello.ts --outDir dist --target ES2020 --watch
tsconfig.json 配置
创建配置文件
# 生成默认配置文件
tsc --init
常用配置选项
{
"compilerOptions": {
/* 基本选项 */
"target": "ES2020", // 编译目标版本
"module": "commonjs", // 模块系统
"outDir": "./dist", // 输出目录
"rootDir": "./src", // 源码目录
"strict": true, // 启用所有严格类型检查
/* 类型检查 */
"noImplicitAny": true, // 禁止隐式 any
"strictNullChecks": true, // 严格的 null 检查
"noUnusedLocals": true, // 检查未使用的变量
"noUnusedParameters": true, // 检查未使用的参数
"noImplicitReturns": true, // 检查每个分支都有返回值
/* 模块解析 */
"moduleResolution": "node", // 模块解析策略
"esModuleInterop": true, // 允许 default 导入
"allowSyntheticDefaultImports": true, // 允许合成默认导入
/* 其他 */
"sourceMap": true, // 生成 source map
"declaration": true, // 生成 .d.ts 声明文件
"removeComments": true // 移除注释
},
"include": ["src/**/*"], // 包含的文件
"exclude": ["node_modules", "dist"] // 排除的文件
}
解释:
target指定编译后的 JavaScript 版本,现代浏览器支持 ES2015+strict开启所有严格模式选项,推荐开启sourceMap生成映射文件,方便调试
使用配置文件编译
# 使用 tsconfig.json 配置编译
tsc
# 指定配置文件
tsc --project tsconfig.build.json
# 监听模式
tsc --watch
VS Code 配置
推荐扩展
- TypeScript Vue Plugin (Volar) - Vue 文件中的 TypeScript 支持
- ESLint - 代码检查
- Prettier - 代码格式化
settings.json 配置
{
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true,
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
}
}
项目结构示例
my-typescript-project/
├── src/
│ ├── index.ts
│ ├── utils/
│ │ └── helpers.ts
│ └── types/
│ └── index.d.ts
├── dist/ # 编译输出目录
├── node_modules/
├── package.json
├── tsconfig.json
└── README.md
与构建工具集成
Webpack 集成
npm install --save-dev ts-loader typescript
// webpack.config.js
module.exports = {
entry: './src/index.ts',
module: {
rules: [
{
test: /\.ts$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
},
resolve: {
extensions: ['.ts', '.js']
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
Vite 集成
Vite 原生支持 TypeScript,无需额外配置:
# 创建 Vite + TypeScript 项目
npm create vite@latest my-app -- --template ts
ts-node 直接运行
ts-node 可以直接运行 TypeScript 代码,无需先编译:
# 安装
npm install --save-dev ts-node
# 运行 TypeScript 文件
npx ts-node src/index.ts
# 在 package.json 中添加脚本
{
"scripts": {
"dev": "ts-node src/index.ts",
"build": "tsc",
"start": "node dist/index.js"
}
}
解释:ts-node 适合开发环境快速测试,生产环境仍需编译为 JavaScript。
类型声明文件
安装类型声明
# 安装 Node.js 类型声明
npm install --save-dev @types/node
# 安装其他库的类型声明
npm install --save-dev @types/lodash
npm install --save-dev @types/express
解释:许多第三方库的类型声明托管在 DefinitelyTyped 仓库中,通过 @types/ 包安装。
创建自定义声明文件
// src/types/custom.d.ts
declare module 'my-library' {
export function doSomething(value: string): number;
export interface Config {
timeout: number;
retries?: number;
}
}
常见问题
1. 类型错误但能运行
TypeScript 的类型检查在编译时进行,类型错误不会阻止 JavaScript 生成:
# 有错误时不生成输出文件
tsc --noEmitOnError
2. 第三方库没有类型
// 创建 declarations.d.ts
declare module 'untyped-library';
3. 配置不生效
确保在正确的目录运行 tsc,并且 tsconfig.json 在项目根目录。
VS Code 调试配置
基本调试配置
在 .vscode/launch.json 中配置调试:
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug TypeScript",
"type": "node",
"request": "launch",
"runtimeExecutable": "node",
"runtimeArgs": ["--nolazy", "-r", "ts-node/register"],
"args": ["${file}"],
"cwd": "${workspaceRoot}",
"internalConsoleOptions": "openOnSessionStart",
"skipFiles": ["<node_internals>/**"]
},
{
"name": "Debug Current TS File",
"type": "node",
"request": "launch",
"program": "${workspaceFolder}/node_modules/ts-node/dist/bin.js",
"args": ["${file}"],
"console": "integratedTerminal"
}
]
}
调试编译后的代码
如果需要调试编译后的 JavaScript 代码:
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Compiled JS",
"type": "node",
"request": "launch",
"program": "${workspaceFolder}/dist/index.js",
"preLaunchTask": "tsc: build - tsconfig.json",
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
"sourceMaps": true
}
]
}
解释:sourceMaps: true 启用源码映射,可以在 .ts 文件中设置断点,调试时会自动映射到编译后的 .js 文件。
使用断点调试
// 在 VS Code 中设置断点
function calculateTotal(items: Item[]): number {
let total = 0; // 点击行号左侧设置断点
for (const item of items) {
total += item.price * item.quantity;
}
return total;
}
// 调试时可以:
// 1. 查看变量值
// 2. 单步执行
// 3. 进入函数内部
// 4. 查看调用堆栈
错误解读
TypeScript 的错误信息通常包含三个部分:错误代码、错误描述和错误位置。理解这些错误信息是解决问题的关键。
常见错误类型
错误 2322:类型不兼容
Type 'string' is not assignable to type 'number'.(2322)
// 问题代码
let age: number = "25"; // 错误:不能将 string 赋给 number
// 解决方案
let age: number = 25;
// 或
let age: number = parseInt("25");
错误 2339:属性不存在
Property 'name' does not exist on type '{ age: number }'.(2339)
// 问题代码
const user = { age: 25 };
console.log(user.name); // 错误:属性 name 不存在
// 解决方案
interface User {
name?: string; // 可选属性
age: number;
}
const user: User = { age: 25 };
console.log(user.name); // 现在正确,类型为 string | undefined
错误 2345:参数类型不匹配
Argument of type 'string' is not assignable to parameter of type 'number'.(2345)
// 问题代码
function greet(name: string): void {
console.log(`Hello, ${name}`);
}
greet(123); // 错误:参数类型不匹配
// 解决方案
greet("张三"); // 传入正确类型
// 或修改函数签名
function greet(name: string | number): void {
console.log(`Hello, ${name}`);
}
错误 2739:缺少必需属性
Type '{ name: string }' is missing the following properties from type 'User': age, email(2739)
// 问题代码
interface User {
name: string;
age: number;
email: string;
}
const user: User = { name: "张三" }; // 错误:缺少 age 和 email
// 解决方案
const user: User = {
name: "张三",
age: 25,
email: "[email protected]"
};
// 或使用 Partial
const partialUser: Partial<User> = { name: "张三" };
错误 2531:对象可能为 null
Object is possibly 'null'.(2531)
// 问题代码
const element = document.getElementById("myInput");
element.value = "hello"; // 错误:element 可能为 null
// 解决方案一:可选链
element?.value; // 安全访问
// 解决方案二:非空断言
element!.value = "hello"; // 断言 element 不为 null
// 解决方案三:条件检查
if (element) {
element.value = "hello";
}
错误 7006:隐式 any 类型
Parameter 'x' implicitly has an 'any' type.(7006)
// 问题代码
function add(x, y) { // 错误:参数隐式为 any
return x + y;
}
// 解决方案
function add(x: number, y: number): number {
return x + y;
}
错误排查技巧
1. 使用 TypeScript 语言服务
VS Code 内置了 TypeScript 语言服务,可以实时显示错误和快速修复:
- 按
F8跳转到下一个错误 - 按
Shift+F8跳转到上一个错误 - 点击错误代码旁的灯泡图标查看快速修复建议
2. 使用 TypeScript Playground
对于复杂的类型问题,可以在 TypeScript Playground 中测试:
// 在 Playground 中可以:
// 1. 查看编译后的 JavaScript
// 2. 查看类型推断结果
// 3. 分享代码片段
3. 启用严格模式逐步修复
// tsconfig.json
{
"compilerOptions": {
"strict": true, // 启用所有严格选项
"noImplicitAny": true,
"strictNullChecks": true
}
}
建议:对于遗留项目,可以逐步启用严格选项,而不是一次性全部开启。
4. 使用 // @ts-expect-error 抑制错误
// 期望下一行有错误,用于测试
// @ts-expect-error
const result: string = 123;
// 如果下一行没有错误,@ts-expect-error 会报错
// @ts-expect-error // 错误:未使用的 @ts-expect-error 指令
const valid: string = "hello";
5. 使用 // @ts-ignore 临时忽略错误
// @ts-ignore // 临时忽略错误,不推荐长期使用
const result: string = 123;
注意:@ts-ignore 和 @ts-expect-error 应该是最后的手段,优先修复根本问题。
开发工具推荐
VS Code 扩展
必装扩展
-
TypeScript Hero - 代码组织工具
- 添加缺失的导入
- 组织导入语句
- 添加 barrel 文件
-
ESLint - 代码检查
npm install --save-dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin -
Prettier - 代码格式化
npm install --save-dev prettier eslint-config-prettier
有用的扩展
- Move TS - 移动 TypeScript 文件并自动更新导入
- Import Cost - 显示导入包的大小
- Error Lens - 在行内显示错误信息
- TypeScript Importer - 自动导入建议
ESLint 配置
创建 .eslintrc.js:
module.exports = {
root: true,
parser: "@typescript-eslint/parser",
plugins: ["@typescript-eslint"],
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"prettier",
],
rules: {
"@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/no-explicit-any": "warn",
"no-console": ["warn", { allow: ["warn", "error"] }],
},
};
Prettier 配置
创建 .prettierrc:
{
"semi": true,
"singleQuote": false,
"tabWidth": 2,
"trailingComma": "es5",
"printWidth": 100
}
package.json scripts 配置
{
"scripts": {
"dev": "ts-node src/index.ts",
"build": "tsc",
"start": "node dist/index.js",
"lint": "eslint src --ext .ts",
"lint:fix": "eslint src --ext .ts --fix",
"format": "prettier --write \"src/**/*.ts\"",
"typecheck": "tsc --noEmit",
"test": "jest"
}
}
Jest 测试配置
安装依赖:
npm install --save-dev jest @types/jest ts-jest
创建 jest.config.js:
module.exports = {
preset: "ts-jest",
testEnvironment: "node",
roots: ["<rootDir>/src"],
testMatch: ["**/__tests__/**/*.ts", "**/*.test.ts"],
collectCoverageFrom: ["src/**/*.ts", "!src/**/*.d.ts"],
};
编写测试:
// src/utils.test.ts
import { add, subtract } from "./utils";
describe("utils", () => {
test("add should sum two numbers", () => {
expect(add(1, 2)).toBe(3);
});
test("subtract should find difference", () => {
expect(subtract(5, 3)).toBe(2);
});
});
快速诊断命令
tsc --noEmit
仅进行类型检查,不生成文件:
tsc --noEmit
用途:在 CI/CD 管道中进行类型检查,或在编译前快速发现类型错误。
tsc --traceResolution
追踪模块解析过程:
tsc --traceResolution
用途:调试模块导入问题,查看 TypeScript 如何解析模块路径。
tsc --showConfig
显示实际使用的配置:
tsc --showConfig
用途:查看 TypeScript 实际使用的配置,帮助调试 tsconfig.json 问题。
小结
本章我们学习了:
- TypeScript 的安装方法
- 编译 TypeScript 文件
tsconfig.json配置选项- VS Code 开发环境配置和调试设置
- 与构建工具的集成
- 使用
ts-node直接运行 - 类型声明文件的使用
- TypeScript 错误解读和排查技巧
- 开发工具推荐和配置
练习
- 创建一个新的 TypeScript 项目,配置 ESLint 和 Prettier
- 配置
tsconfig.json,开启严格模式 - 编写一个简单的 TypeScript 程序并使用 VS Code 调试
- 尝试解读并修复常见的 TypeScript 错误