跳到主要内容

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 配置

推荐扩展

  1. TypeScript Vue Plugin (Volar) - Vue 文件中的 TypeScript 支持
  2. ESLint - 代码检查
  3. 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 扩展

必装扩展

  1. TypeScript Hero - 代码组织工具

    • 添加缺失的导入
    • 组织导入语句
    • 添加 barrel 文件
  2. ESLint - 代码检查

    npm install --save-dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
  3. 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 问题。

小结

本章我们学习了:

  1. TypeScript 的安装方法
  2. 编译 TypeScript 文件
  3. tsconfig.json 配置选项
  4. VS Code 开发环境配置和调试设置
  5. 与构建工具的集成
  6. 使用 ts-node 直接运行
  7. 类型声明文件的使用
  8. TypeScript 错误解读和排查技巧
  9. 开发工具推荐和配置

练习

  1. 创建一个新的 TypeScript 项目,配置 ESLint 和 Prettier
  2. 配置 tsconfig.json,开启严格模式
  3. 编写一个简单的 TypeScript 程序并使用 VS Code 调试
  4. 尝试解读并修复常见的 TypeScript 错误