泛型是 TS 实现可复用、强类型代码的核心工具,简单说就是给类型加一个“占位符”。它的主要用途是封装通用的函数、类、接口,让它们能适配多种数据类型,比如通用的数组处理函数、请求响应接口、数据容器类。 优势非常明显:第一,替代 any,完全保留类型安全,编译时就能校验错误;第二,高度复用,一份代码适配所有类型,不用重复编写;第三,灵活性拉满,调用时可以手动指定类型,也能让 TS 自动推断。它兼顾了代码复用和类型严谨性,是开发通用组件、工具库的必备语法,比写死类型更灵活,比任意类型更安全。
用泛型创建可重用组件特别简单,核心是定义时用<T>占位,调用时自动 / 手动传类型。比如写通用函数,用function fn<T>(arg: T): T {},T 代表任意类型;写通用类,用class Container<T> { data: T };写通用接口,用interface Res<T> { code: number; data: T }。 调用时直接传数据,TS 会自动推导类型,也可以手动指定fn<string>('hello')。这样一个组件能适配 string、number、对象等所有类型,不用重复编写逻辑,还能严格约束输入输出。无论是工具函数、UI 组件还是请求封装,泛型都能让组件一次编写、处处通用。
TS 高级类型是基于基础类型组合的类型工具,核心包含这几种:交叉类型 &、联合类型 |、条件类型、映射类型、索引类型、keyof/typeof、infer 推断类型,还有 Partial、Required 等内置工具类型。 它们的用途各有侧重:交叉类型合并多个类型,联合类型支持多选类型;条件类型做类型判断;映射类型批量修改对象属性;索引类型提取属性类型;infer 提取函数 / 泛型内部类型。内置工具类型简化了常用操作,高级类型能处理复杂的业务类型逻辑,自动生成类型,替代手写冗余代码,让 TS 类型系统更强大、更灵活。
高阶类型(高级类型)主要用在复杂业务封装、框架开发、工具库编写这些场景。第一,封装 API 响应类型,用泛型 + 索引类型统一处理所有接口返回,不用单独定义;第二,表单开发,用 Partial/Required 动态调整属性是否必填;第三,联合类型穷尽校验,用条件类型 +never 避免漏判;第四,提取函数参数、返回值类型,用 infer 一键生成;第五,状态管理,用映射类型生成只读状态。还能适配第三方库,补全缺失的类型定义,让复杂类型逻辑自动化,大幅减少手写代码。
联合类型|和交叉类型&是提升类型灵活性的基础,也是日常最常用的高级类型。联合类型代表多选一,比如type Data = string | number,让变量、函数参数接收多种类型值,适配不同业务场景;交叉类型代表类型合并,比如type User = Base & Info,把多个类型的属性整合在一起,实现类型复用。 两者配合使用效果更好:联合类型处理多类型输入,交叉类型组合复杂对象。它们完全替代了不安全的 any,也避免了重复定义类型,让代码既灵活适配各种数据,又不丢失类型安全,简单易用还能解决大部分类型需求。
条件类型是 TS 的类型三元表达式,语法是T extends U ? X : Y,能根据类型条件自动推导结果,是实现动态类型的核心。它最强大的地方是结合infer关键字,直接提取类型内部的信息,比如函数返回值、数组元素、Promise 泛型类型。 比如写type Return<T> = T extends (...args: any[]) => infer R ? R : never,就能自动提取函数的返回类型。不用手动指定类型,TS 会根据传入的泛型,自动计算出目标类型。它能实现智能类型推导,适配不同输入生成对应类型,让复杂的通用类型封装变得简单。
映射类型的核心作用是基于旧类型,批量生成新类型,不用重复手写对象属性,极大减少冗余代码。基础用法就是批量把属性改成可选、只读、必填,内置的 Partial、Readonly 都是映射类型。 高级用法更强大:结合 keyof、条件类型、as 重映射,可以过滤属性、修改属性类型、剔除指定键,甚至生成全新的类型结构。比如可以自定义类型,只保留对象中的数字类型属性,或者把所有属性转为非空。它是处理复杂对象类型的利器,能根据业务需求动态改造类型,灵活又高效。
索引类型使用很简单,用类型[键]的语法,就能获取对象类型中某个属性的类型,比如User['name']直接拿到 string 类型。结合泛型使用更实用,比如写通用取值函数function get<T, K extends keyof T>(obj: T, key: K): T[K] {}。 它的好处很实在:第一,类型安全,写错属性名直接编译报错;第二,复用类型,不用重复定义属性类型;第三,动态关联,适配任意对象类型。彻底避免了硬编码类型的问题,处理对象属性时,编译期就能拦截错误,让代码更健壮。
keyof和索引访问T[K]是操作对象类型的黄金搭档。keyof会取出对象类型的所有键,生成联合类型,比如keyof User得到'name'|'age';索引访问则是根据键,取出对应的属性类型。 它们的核心用途:封装通用的对象操作工具,保证键名和值的类型严格匹配;提取对象的键和属性类型,实现类型复用;配合泛型、映射类型,生成动态的业务类型。比如写通用的表单处理、数据遍历函数,用它们约束类型,彻底杜绝键名写错、类型不匹配的问题,让类型关联精准无误。
索引签名专门用来处理属性名不确定的动态对象,语法是{ [键名: 字符串/数字]: 值类型 },比如type DynObj = { [key: string]: string | number }。 它适合接口返回的动态字段、表单数据、配置项等场景,不用提前定义所有属性,灵活适配任意属性名。使用时注意:同一类型只能有一个字符串或数字索引,声明的固定属性必须匹配索引类型。它比 any 安全得多,既能支持动态属性,又能严格约束值的类型,避免动态数据导致的运行时类型错误。
类型守卫是 TS 的类型缩小工具,专门解决联合类型、未知类型的模糊问题,核心是类型保护机制。它通过特定的语法或函数,告诉编译器变量的具体类型,让 TS 在代码块内精准识别类型。 常用的类型守卫有四种:typeof 判断基础类型、instanceof 判断类实例、in 判断对象独有属性、自定义类型谓词函数。比如执行typeof x === 'string'后,代码块里的 x 会被自动识别为 string 类型。它完全替代了不安全的类型断言,是 TS 保证类型安全、处理不确定类型的核心手段。
联合类型默认只能访问共有属性,用类型守卫就能精准区分每一种子类型,是优化类型检查的最佳方案。常用方法:用 typeof 区分基础类型,in 判断对象独有属性,自定义类型谓词函数做复杂判断。 比如联合类型{type:'a';num:number} | {type:'b';str:string},用if(item.type === 'a')判断后,TS 会自动识别对应类型。优化效果拉满:替代 any 和断言,编译期拦截错误;代码可读性更高;配合 switch+never 兜底,还能避免漏判。大幅提升了联合类型的检查效率和安全性,是业务开发的必备技巧。