01. TypeScript 是什么、解决了什么问题
TypeScript 是 JavaScript 的超集——所有合法的 JS 代码都是合法的 TS 代码。它在 JS 之上加了类型系统,编译时(不是运行时)做类型检查。
TypeScript 解决的问题:
1. 类型错误提前发现——拼错属性名、传错参数类型,在写代码时 IDE 就报红,不用等到运行才发现。
2. 更好的 IDE 体验——自动补全、参数提示、重构工具,全都基于类型信息。
3. 自文档化——接口和类型定义就是最好的 API 文档。新同事看代码就知道这个函数要什么参数返回什么结果。
4. 大型项目的可维护性——几万行 JS 代码改了不敢部署?TS 让你改之前编译就知道哪些地方受影响。
TS 代码经过 tsc(TypeScript Compiler)编译成 JS 才能运行。类型信息在编译后全被擦除,不影响运行时性能。
bash
# 安装 TypeScript
npm install -g typescript
# 初始化项目
tsc --init # 创建 tsconfig.json
# 编译
tsc # 编译整个项目
tsc --watch # 监视模式,文件一变就编译
tsc --noEmit # 只检查类型,不输出 JS 文件02. 基础类型注解
TypeScript 的类型注解写在一个冒号后面:变量: 类型。基本类型有 string、number、boolean、null、undefined、any、unknown。
类型推断——大部分情况下你不写类型注解 TS 也能根据初始值自动推断类型。let name = 'Alice' 自动推断为 string。只有初始值无法推断时(如函数参数)才必须写类型。
any——任何类型,相当于关闭类型检查。别滥用——用了 any 等于放弃 TS 的保护。unknown——安全的 any,在对 unknown 类型的值做任何操作前必须先类型检查。
数组写法:number[] 或 Array<number>。元组(Tuple):[string, number] 固定长度和类型的数组。
typescript
// 基础类型
let name: string = 'Alice';
let age: number = 36;
let isActive: boolean = true;
// 类型推断(不需要写类型注解)
let city = 'Beijing'; // TS 自动推断为 string
// any vs unknown
let data: any = 123;
data.toUpperCase(); // 不报错但运行时报错!
let info: unknown = 123;
// info.toUpperCase(); // 编译报错!必须先检查类型
if (typeof info === 'string') {
info.toUpperCase(); // 安全了
}
// 数组和元组
let list: number[] = [1, 2, 3];
let tuple: [string, number] = ['Alice', 36];unknown 是 any 的安全替代——对 unknown 类型的值做任何操作前都必须缩小类型范围。养成尽量不用 any 的习惯。
03. 函数类型
函数的类型包括参数类型和返回值类型。参数类型必须写(除非有默认值),返回值类型可省略(TS 能推断)。
可选参数:参数名后加 ?——表示这个参数可以不传。默认参数:参数名 = 默认值——跟 JS 一样但 TS 能自动推断类型。
剩余参数:...args: number[]——跟 JS 一样但是要加类型注解。
函数重载:同一个函数可以有不同的参数和返回值组合。用多个函数签名加一个实现签名。
void 返回类型——函数没有返回值(或返回 undefined)。never——函数永远不会执行完(抛异常或死循环)。
typescript
// 函数类型
function add(a: number, b: number): number {
return a + b;
}
// 可选参数和默认值
function greet(name: string, greeting?: string): string {
return `${greeting || 'Hello'}, ${name}`;
}
function multiply(a: number, b = 1): number {
return a * b; // b 自动推断为 number
}
// 函数重载
function process(x: string): string;
function process(x: number): number;
function process(x: string | number): string | number {
if (typeof x === 'string') return x.toUpperCase();
return x * 2;
}函数参数的类型注解不能省略(除非有默认值可以推断)。如果参数没写类型,TS 会隐式标为 any——在 strict 模式下会报错。
04. tsconfig.json——TypeScript 的配置文件
tsconfig.json 是 TypeScript 项目的核心配置文件。几个最常用的选项:
target——编译输出到哪个 JS 版本(ES5/ES6/ESNext)。现代项目一般 ESNext 或 ES2022。
module——使用什么模块系统(CommonJS/ESNext)。Node.js 项目用 CommonJS,前端打包的项目用 ESNext 让打包工具处理。
strict——严格模式的总开关,开启后会自动启用 noImplicitAny、strictNullChecks 等所有严格检查。强烈建议开启!
outDir——编译输出目录(如 ./dist)。
rootDir——源代码目录(如 ./src)。
include/exclude——指定包含/排除哪些文件。
paths——路径别名。把 @/utils 映射到 src/utils,不用写 ../../utils。配合打包工具(Webpack/Vite)的别名一起用。
json
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"strict": true,
"outDir": "./dist",
"rootDir": "./src",
"esModuleInterop": true,
"skipLibCheck": true,
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}strict: true 一开始可能报很多错,但这些都是潜在的 bug。习惯严格模式后写出来的代码质量高一大截。
05. 枚举与 literal 类型
枚举(enum)把一组相关常量集合在一起。TS 的 enum 编译成 JS 后会变成双向映射的对象(数字枚举)或字符串映射。
const enum——编译时内联,不生成 JS 对象。性能更好但不能运行时反向查找。
有些团队不喜欢 enum(因为编译后多出 JS 代码),用 union type 代替:type Color = 'red' | 'green' | 'blue'。这叫字面量类型加联合类型——字符串枚举值,编译后零开销。
选 enum 还是 union:需要反向查找(从值找键名)用 enum,只做类型约束用 union type。现代 TS 项目倾向用 union type。
typescript
// enum
enum Direction {
North = 'N',
South = 'S',
East = 'E',
West = 'W'
}
function move(dir: Direction) {}
move(Direction.North);
// const enum(编译后无额外 JS 代码)
const enum Size { Small, Medium, Large }
const s: Size = Size.Small;
// union type 替代 enum
// type Direction = 'North' | 'South' | 'East' | 'West';
// function move(dir: Direction) {}
// move('North');const enum 编译后被内联替换为常量值,不留任何 enum 对象。但有些打包工具在 transpileOnly 模式下需要额外配置才能支持 const enum。
知识测验
第 1/5 题正确 0
TypeScript 的类型检查发生在什么阶段?
下一节
下一节 类型系统