TypeScript 知识点速记总结
TypeScript(TS) 是 JavaScript(JS) 的强类型超集,在JS基础上新增静态类型系统,编译期做类型检查,最终编译为纯JS运行,完全兼容所有JS语法,核心解决JS弱类型带来的线上隐患、大型项目可维护性差、协作效率低的问题。
一、核心基础认知
- 核心特性:静态类型检查、类型推断、类型注解、编译时校验、ES6+ 全特性支持、向下兼容。
- 运行逻辑:TS 不能直接在浏览器/Node.js 运行,需通过 tsc 编译器 / ts-node / Vite/Webpack 等工具编译为 JS 后执行。
- 环境核心 :全局安装
typescript包,核心命令tsc xxx.ts编译文件,tsc --init生成tsconfig.json配置文件。
二、基础原始类型 & 特殊类型(TS类型基石)
1. 基础原始类型(和JS一一对应,加类型注解)
ts
// 语法:变量: 类型 = 值
const str: string = "hello"; // 字符串
const num: number = 123; // 数字(含整数、浮点数、Infinity、NaN)
const bool: boolean = true; // 布尔值
const sym: symbol = Symbol(); // 唯一值
const big: bigint = 100n; // 大整数
const nul: null = null; // 空值
const und: undefined = undefined; // 未定义
- 补充:开启
strictNullChecks后,null/undefined只能赋值给自身、any、unknown,关闭时可赋值给任意类型。
2. 核心特殊类型(面试高频)
| 类型 | 核心定义 | 适用场景 |
|---|---|---|
any |
放弃所有类型检查,TS 对其不做任何校验,可赋值给任意类型,也可接收任意类型的值 | 临时兼容老JS代码,严禁滥用,会让TS失去类型保护意义 |
unknown |
安全版any,所有类型都可赋值给unknown,但unknown只能赋值给any/unknown,必须做类型收窄后才能操作 |
不确定入参类型的场景,替代any做类型安全兜底 |
void |
无返回值,对应函数没有return或return undefined |
定义无返回值的函数 |
never |
永不存在的值的类型,是所有类型的子类型,没有类型可以赋值给never(除了never本身) |
函数抛出错误、无限循环、穷尽性检查(联合类型兜底) |
三、常用复合类型
1. 数组类型
两种核心写法,支持只读、联合类型约束
ts
// 写法1:类型+方括号(推荐)
const arr1: number[] = [1,2,3];
// 写法2:泛型数组
const arr2: Array<string> = ["a","b"];
// 只读数组
const arr3: readonly number[] = [1,2,3];
// 联合类型数组
const arr4: (string | number)[] = [1,"a",2];
2. 元组 Tuple
固定长度、固定位置类型的数组,严格约束每一项的类型和数量
ts
const user: [string, number, boolean?] = ["张三", 18]; // 可选元素
const list: [string, ...number[]] = ["a",1,2,3]; // 剩余元素
const readonlyTuple: readonly [string, number] = ["a",1]; // 只读元组
3. 枚举 Enum
给一组数值/字符串赋予友好的名字,分为三类:
ts
// 1. 数字枚举(默认从0递增,支持反向映射)
enum Direction { Up, Down, Left, Right }
// 2. 字符串枚举(无反向映射)
enum Msg { Success = "200", Fail = "500" }
// 3. 常量枚举(const enum,编译后会被内联,减少代码体积)
const enum Status { On, Off }
4. 函数类型
完整约束函数的入参、返回值,支持多种进阶用法
ts
// 基础写法:参数类型 + 返回值类型
function add(a: number, b: number): number { return a + b; }
// 箭头函数类型
const add2: (a: number, b: number) => number = (a,b) => a + b;
// 进阶特性
// 1. 可选参数(?,必须在必选参数后)
function fn(a: number, b?: number) {}
// 2. 默认参数
function fn2(a: number, b: number = 10) {}
// 3. 剩余参数
function sum(...nums: number[]) {}
// 4. 函数重载(先声明重载签名,再写实现签名)
function getInfo(id: number): {id: number};
function getInfo(name: string): {name: string};
function getInfo(value: number | string) {
if(typeof value === "number") return {id: value};
return {name: value};
}
5. 接口 Interface
专门用于定义对象/函数/类的类型结构,核心是描述形状,支持继承、合并
ts
// 基础对象接口
interface User {
readonly id: number; // 只读属性
name: string;
age?: number; // 可选属性
[key: string]: any; // 任意属性(索引签名)
}
// 接口继承
interface VipUser extends User {
vipLevel: number;
}
// 接口合并:同名接口会自动合并属性
interface User {
gender: string;
}
6. 类型别名 Type
给任意类型起别名,比interface适用范围更广,支持联合、交叉、原始类型等
ts
// 基础用法
type User = {
name: string;
age: number;
};
// 支持联合类型、原始类型
type Sex = "男" | "女";
type Num = number;
// 交叉类型
type VipUser = User & { vipLevel: number };
高频考点:interface vs type 核心区别
| 特性 | interface | type |
|---|---|---|
| 核心用途 | 主要定义对象、类的结构 | 定义任意类型(原始值、联合、交叉、元组等) |
| 继承/扩展 | 用extends继承 |
用&交叉类型合并 |
| 同名合并 | 支持(声明合并) | 不支持,同名会报错 |
| 实现 | 类可以用implements实现接口 |
类只能实现联合类型以外的type |
四、核心类型语法
-
联合类型
|:满足多个类型中的任意一个即可tstype Value = string | number | boolean; -
交叉类型
&:必须同时满足所有类型的约束,多用于合并对象类型tstype A = { a: number }; type B = { b: string }; type C = A & B; // 必须同时有a和b属性 -
字面量类型 :把值本身作为类型,配合联合类型实现枚举效果
tstype Status = 0 | 1 | 2; type Method = "GET" | "POST" | "PUT" | "DELETE"; -
模板字面量类型 :基于字符串模板拼接生成类型
tstype EventName = `${string}Change`; // 匹配任意以Change结尾的字符串 type Key = `user_${"id" | "name" | "age"}`; // user_id | user_name | user_age -
类型断言 :手动告诉TS编译器某个值的具体类型,绕过类型推断,不改变运行时
ts// 两种写法,推荐as语法 const str = "hello" as unknown as number; // 双重断言,极端场景使用 const num = <number>123; // 尖括号写法,JSX中不兼容 -
非空断言
!:告诉编译器某个值一定不是null/undefined,跳过非空检查tsconst dom = document.getElementById("app")!; // 断言dom一定存在
五、类型守卫 & 类型缩小
核心作用:把宽泛的联合类型,收窄到具体的类型,让TS能精准做类型校验,是TS类型安全的核心手段。
| 类型守卫方式 | 适用场景 | 示例 |
|---|---|---|
typeof |
原始类型收窄 | if(typeof value === "string") { // 这里value被收窄为string } |
instanceof |
类实例收窄 | if(value instanceof Date) { // 这里value被收窄为Date } |
in |
对象属性收窄 | if("name" in value) { // 这里value被收窄为包含name属性的类型 } |
| 可辨识联合 | 联合类型对象收窄 | 给联合类型的每个对象加唯一的type字段,通过type判断收窄 |
类型谓词 is |
自定义类型守卫 | function isString(val: unknown): val is string { return typeof val === "string" } |
等值判断(===/!==) |
字面量类型收窄 | if(status === 200) { // 收窄为字面量200 } |
六、泛型(TS核心灵魂)
核心定义:类型参数化,把类型当成参数传入,实现类型复用,让类型和入参/返回值强关联,而不是写死固定类型。
1. 基础用法
ts
// 函数泛型
function getData<T>(value: T): T {
return value;
}
// 调用时指定类型,或TS自动推断
getData<string>("hello");
getData(123); // 自动推断为number
// 多泛型参数
function swap<A, B>([a, b]: [A, B]): [B, A] {
return [b, a];
}
2. 泛型约束
用extends限制泛型的范围,避免传入不符合要求的类型
ts
// 约束泛型必须有length属性
interface HasLength {
length: number;
}
function getLength<T extends HasLength>(value: T): number {
return value.length;
}
3. 泛型进阶用法
- 接口泛型:
interface Res<T> { code: number; data: T; msg: string } - 类泛型:
class Queue<T> { private list: T[] = [] } - 泛型默认值:
function fn<T = string>(val?: T) {} - 条件泛型:
T extends U ? X : Y
七、TS内置工具类型(全量速记)
TS 内置了大量基于泛型实现的工具类型,用于快速处理类型转换,面试高频,核心如下:
| 工具类型 | 核心作用 |
|---|---|
Partial<T> |
把T的所有属性变为可选 |
Required<T> |
把T的所有属性变为必选 |
Readonly<T> |
把T的所有属性变为只读 |
Pick<T, K> |
从T中挑选指定的K属性,生成新类型 |
Omit<T, K> |
从T中排除指定的K属性,生成新类型 |
Exclude<T, U> |
从联合类型T中排除可以赋值给U的类型 |
Extract<T, U> |
从联合类型T中提取可以赋值给U的类型 |
Record<K, T> |
定义键为K类型、值为T类型的对象类型 |
ReturnType<T> |
获取函数类型T的返回值类型 |
Parameters<T> |
获取函数类型T的参数类型,生成元组 |
Awaited<T> |
解包Promise的返回值类型,处理async/await场景 |
NonNullable<T> |
从T中排除null和undefined |
八、高级类型操作
-
条件类型 :基于三元表达式的类型判断,支持分布式条件类型
tstype IsNumber<T> = T extends number ? true : false; type A = IsNumber<1>; // true type B = IsNumber<string>; // false -
映射类型 :通过
in关键字遍历类型的键,生成新类型,是内置工具类型的实现基础tstype MyPartial<T> = { [K in keyof T]?: T[K] }; -
infer类型推断 :在条件类型中推断类型,用于提取目标类型ts// 实现ReturnType type MyReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : never; -
索引访问类型 :通过
T[K]获取类型中指定属性的类型tsinterface User { name: string; age: number } type UserName = User["name"]; // string -
keyof索引类型查询 :获取类型的所有键,生成联合类型tstype UserKeys = keyof User; // "name" | "age"
九、面向对象特性
- 类的修饰符
public:默认,公有属性/方法,任何地方都可访问private:私有,只能在类内部访问,子类也不能访问protected:受保护,只能在类内部和子类中访问readonly:只读,只能在声明时/构造函数中赋值static:静态,属于类本身,不属于实例,通过类名访问
- 类的存取器 :
get/set拦截属性的读取和赋值 - 抽象类
abstract:不能实例化,只能被继承,可包含抽象方法(只有声明,无实现,子类必须实现) - 类实现接口 :用
implements关键字,类必须实现接口中定义的所有属性和方法
十、模块与类型声明
-
ES模块 :完全兼容ES6的
import/export语法,支持模块导入导出类型ts// 类型导入导出,推荐用type前缀,编译后会被移除 export type User = { name: string }; import type { User } from "./user"; -
类型声明文件
.d.ts:专门用于写类型声明,给JS库提供TS类型支持,全局类型定义 -
declare 声明 :用于声明全局变量、模块、函数、命名空间,告诉TS编译器对应的类型
ts// 声明全局变量 declare const window: Window; // 声明模块 declare module "*.vue"; declare module "lodash"; -
命名空间
namespace:用于在全局作用域内划分模块,避免命名冲突,现在大多被ES模块替代,多用于类型声明文件中。
十一、tsconfig.json 核心配置
TS项目的编译配置文件,核心配置项速记:
json
{
"compilerOptions": {
"target": "ES6", // 编译后的JS目标版本
"module": "ESNext", // 编译后的模块规范
"rootDir": "./src", // 源码根目录
"outDir": "./dist", // 编译输出目录
"strict": true, // 开启所有严格类型检查,推荐开启
"esModuleInterop": true, // 兼容ES模块和CommonJS模块的互操作
"skipLibCheck": true, // 跳过声明文件的类型检查,提升编译速度
"moduleResolution": "Node", // 模块解析策略
"resolveJsonModule": true, // 支持导入JSON文件
"jsx": "react-jsx", // 处理JSX语法,React项目用
"declaration": true, // 生成对应的.d.ts类型声明文件
"sourceMap": true // 生成sourceMap文件,方便调试
},
"include": ["src/**/*"], // 指定要编译的文件
"exclude": ["node_modules", "dist"] // 指定要排除的文件
}