
阅读本文你能学到什么类型断言是什么as 怎么用泛型是什么为什么需要它泛型接口、泛型别名、泛型函数的基本用法泛型约束的作用与用法前言第四篇我们搞定了字面量类型和类型推论。但实际项目中还有两个绕不开的问题你比 TS 更清楚某个值的类型怎么告诉它“相信我”又或者写一个函数它能接收任意类型又能保留传入的类型信息——怎么让类型跟着参数走第一个问题的答案是类型断言第二个是泛型。这一篇咱们就把这两个技能一起搞定。一、类型断言1.1 什么是类型断言类型断言是告诉 TypeScript 编译器“我知道这个值是什么类型你按我说的来”。它不会在运行时改变值只是让 TS 通过编译。下面通过两个常见场景来理解它的用法。示例一DOM 元素获取比如document.getElementById(username)TypeScript 只知道它返回的是HTMLElement | null——它只知道页面上有个元素叫username但不知道它具体是什么标签可能是input也可能是div。但作为开发者你清楚这个username对应的就是一个输入框constusernameInputdocument.getElementById(username)asHTMLInputElement// 现在 TS 知道它是 HTMLInputElement可以放心访问 .valueconsole.log(usernameInput.value)// ✅示例二处理unknown类型unknown类型的值不能直接使用需要用断言告诉 TS 它到底是什么类型。letvalue:unknownHello// value.length // ❌ 报错value 是 unknownletlen(valueasstring).length// ✅ 断言为 string 后可以访问1.2 语法推荐使用asTypeScript 有两种断言语法类型值和值 as 类型。在.tsx文件中尖括号语法会与 JSX 标签产生解析冲突所以推荐统一使用as。// ❌ 不推荐尖括号语法在 JSX 中会冲突letvaluestringhello// ✅ 推荐as 语法letvaluehelloasstring1.3as const断言除了用as指定类型TypeScript 还提供了as const用于控制类型推断的精度——它告诉 TypeScript 把类型推断为最精确的字面量类型。// 没有 as constletcolorred// 推断为 string// 有 as constletcolorredasconst// 推断为 red// 对象的 as constconstconfig{url:/api,method:GET}asconst// 推断为{ readonly url: /api; readonly method: GET }as const在需要精确字面量类型的场景非常有用比如定义路由配置、常量对象等。1.4 类型断言的注意事项类型断言只能够“欺骗”TypeScript 编译器无法避免运行时的错误。滥用类型断言可能会导致运行时错误。functionprocessValue(value:string|number){// 假设我们断言 value 是 numberconstnumvalueasnumberconsole.log(num.toFixed(2))}processValue(hello)// ❌ 编译通过但运行时报错num.toFixed is not a function 给新手的提醒类型断言应该在你比 TS 更清楚类型的时候使用而不是用来绕过类型检查。如果你不确定值的类型建议先用typeof或instanceof在代码里做判断而不是直接用断言。二、泛型2.1 什么是泛型为什么需要它泛型Generics是指在定义接口、函数等类型的时候不预先指定具体的类型而在使用的时候再指定类型的一种特性。使用泛型可以复用类型并且让类型更加灵活。思考一下下面的两种数据结构如何使用interface接口实现类型注解这样做有什么问题// 用户数据interfaceUserData{code:numbermessage:stringdata:{id:number;name:string}}// 商品数据interfaceProductData{code:numbermessage:stringdata:{id:number;name:string;price:number}}我们可以对比下数据结构这两个接口的结构完全一样只有data的类型不同。如果每种数据类型都写一个接口代码会变得非常冗余——泛型就是来解决这个问题的。使用泛型后只需要定义一次interfaceResponseDataT{code:numbermessage:stringdata:T}2.2 泛型接口在接口interface后面使用T声明泛型参数接口里的其他成员都可以使用该参数的类型。语法interface 接口名T { ... }// 定义泛型接口interfaceResponseDataT{code:numbermessage:stringdata:T}// 使用泛型接口interfaceUser{id:numbername:string}interfaceProduct{id:numbername:stringprice:number}constuserResponse:ResponseDataUser{code:200,message:获取用户成功,data:{id:1,name:张三}}constproductResponse:ResponseDataProduct{code:200,message:获取商品成功,data:{id:1001,name:手机,price:2999}}我们可以把泛型理解成一个函数——T就像类型的“参数”可以传一个也可以传多个比如ResponseDataT、ResponseDataT, U。2.3 泛型别名在类型别名type的后面使用T声明泛型参数类型别名里的其他成员都可以使用该参数的类型。语法type 类型别名T { ... }// 定义泛型别名typeResponseDataT{code:numbermessage:stringdata:T}typeUser{id:numbername:string}constresponse:ResponseDataUser{code:200,message:获取用户成功,data:{id:1,name:张三}}2.4 泛型函数在函数名称的后面使用T声明泛型参数整个函数中参数、返回值、函数体都可以使用该参数的类型。语法function 函数名T(参数: T): T { ... }// 需求创建一个 createArray 函数// 它可以创建一个指定长度的数组同时将每一项都填充一个默认值多种类型functioncreateArrayT(length:number,defaultValue:T):T[]{constarrnewArray(length)for(leti0;ilength;i){arr[i]defaultValue}returnarr}// 使用示例conststrArraycreateArraystring(3,hello)// [hello, hello, hello]constnumArraycreateArraynumber(3,100)// [100, 100, 100]constboolArraycreateArrayboolean(3,true)// [true, true, true]// 也可以让 TS 自动推断类型constinferredArraycreateArray(3,hello)// TS 自动推断为 string[]2.5 泛型约束泛型的特点就是灵活不确定有些时候泛型函数的内部需要访问一些特定类型的数据才有的属性此时会有类型错误。functiongetLengthT(value:T):number{// ❌ 报错T 类型上不一定有 length 属性returnvalue.length}解决方案通过泛型约束来解决——使用extends关键字让传入的类型必须满足某个条件。语法T extends 类型—— 限制T必须是某个类型的子类型。// 定义一个有 length 属性的接口interfaceLength{length:number}// 约束T 必须具有 length 属性functiongetLengthTextendsLength(value:T):number{returnvalue.length// ✅ 现在安全了}getLength(hello)// ✅ 字符串有 lengthgetLength([1,2,3])// ✅ 数组有 lengthgetLength(abc)// ✅// getLength(123) // ❌ 报错数字没有 length 属性三、开发中的常见错误与避坑指南常见错误原因解决方法滥用类型断言掩盖真实类型错误断言只在编译时生效运行时无法保证类型正确先用typeof或instanceof做判断断言只在你 100% 确定时使用泛型函数内部访问属性报错泛型太灵活TS 无法确认类型是否有该属性使用泛型约束extends限制类型四、本篇小结知识点示例说明类型断言 asvalue as string告诉 TS 值的类型as constred as const推断为最精确的字面量类型泛型接口interface ResT { data: T }接口中使用泛型泛型别名type ResT { data: T }类型别名中使用泛型泛型函数function fnT(v: T): T函数中使用泛型泛型约束T extends Length限制 T 必须满足某个条件核心记忆口诀断言用 as泛型占位 T 少不了。约束用 extends 定边界复用灵活又可靠。参考资料TypeScript 官方文档 —— 类型断言TypeScript 官方文档 —— 泛型上一篇TypeScript 核心语法进阶 —— 字面量类型与类型推论下一篇TypeScript 核心语法应用 —— Vue 3 中的使用上