TypeScript 核心语法应用 —— Vue 3 中的使用(上)

发布时间:2026/8/22 16:12:51
TypeScript 核心语法应用 —— Vue 3 中的使用(上) 阅读本文你能学到什么如何为ref、reactive、computed标注类型如何为事件处理函数标注类型如何为模板引用标注类型如何处理对象的非空值场景前言前面五篇我们学完了 TypeScript 的核心语法——类型注解、接口、泛型、类型断言……学完之后你可能会有疑惑这些语法在 Vue 3 组件中怎么用这一篇就来看看。一、Vue 3 TS 项目环境使用 Vue 官方脚手架创建项目时直接选择TypeScript即可npmcreate vuelatest# 根据提示选择 TypeScript创建完成后项目会自动生成tsconfig.json配置文件不需要手动配置。 本文所有示例均基于script setup langts语法这是 Vue 官方推荐的组合式 API 写法。 项目创建的具体步骤可参考 Vue 官方文档。二、为什么需要标注类型在 Vue 3 中为数据标注类型核心好处有两个赋值时 TS 会校验数据类型是否匹配使用时编辑器会提供准确的代码提示看一个简单的对比import{reactive}fromvue// ❌ 没有标注类型constformreactive({username:,password:})form.username100// ✅ 不报错但 username 应该是 string// ✅ 标注了类型interfaceForm{username:stringpassword:string}constformreactiveForm({username:,password:})form.username100// ❌ 报错Type number is not assignable to type string有了类型约束赋值时的错误能被提前发现编辑器也能给出准确的代码提示。如下图所示输入form.时编辑器会提示 form 的属性username和password。三、为 ref 标注类型ref 和 TS 的配合通常分为两种方式类型推导和泛型指定类型。3.1 类型推导推荐简单数据如果初始值足够明确TypeScript 可以自动推导出类型import{ref}fromvueconstcountref(0)// 推导为 Refnumberconstnameref(Jack)// 推导为 RefstringconstisLoadingref(false)// 推导为 Refboolean如果 ref 没有初始值TypeScript 会自动推导为联合类型包含undefined赋值时同样需要符合类型要求constagerefnumber()// 推导为 Refnumber | undefined3.2 泛型指定类型推荐复杂数据当类型为复杂类型如联合类型如number | null、对象、数组用泛型指定类型import{ref}fromvue// 联合类型constyearrefnumber|null(null)year.value2026// ✅year.value2026// ❌ 报错Type string is not assignable to type number// 对象类型interfaceUser{id:numbername:stringage:number}constuserrefUser|null(null)user.value{id:1,name:张三,age:18}用泛型指定类型不仅对 value 的赋值和初始值做了类型约束使用时也有准确的代码提示效果和第二章展示的类似。四、为 reactive 标注类型reactive 和 TS 的配合通常也分为两种方式类型推导和泛型指定类型。4.1 类型推导推荐如果根据默认参数推导出的类型符合要求直接使用类型推导即可import{reactive}fromvueconststatereactive({count:0,name:Jack})// state 的类型为{ count: number; name: string }4.2 泛型指定类型类型不匹配时使用如果默认对象推导出的类型不满足要求可以使用泛型显式指定类型import{reactive}fromvueinterfaceState{count:numbername:stringisLoading:boolean}conststatereactiveState({count:0,name:Jack,isLoading:false})state.count10state.isLoadingtruestate.count10// ❌ 报错Type number is not assignable to type string显式标注类型不仅对属性赋值做了类型约束reactive的初始值也需要满足类型要求使用时也有准确的代码提示如下图所示。五、为 computed 标注类型计算属性由已知的响应式数据计算得到依赖的数据类型一旦确定TypeScript 会自动推导出计算属性的类型。因此多数情况下不需要手动标注类型TS 会提供准确的代码提示。constcountref(0)// 推导为 RefnumberconstdoubleCountcomputed((){returncount.value*2})// 推导为 ComputedRefnumber如果计算逻辑较复杂或者需要确保返回类型符合预期也可以显式指定interfaceProduct{id:stringname:stringprice:number}constproductsrefProduct[]([{id:1001,name:男鞋,price:299},{id:1002,name:女鞋,price:205},{id:1003,name:衬衫,price:99}])// 计算总价显式指定类型consttotalPricecomputednumber((){returnproducts.value.reduce((sum,item)sumitem.price,0)})// 过滤价格大于 200 的商品自动推导constexpensiveProductscomputed((){returnproducts.value.filter(itemitem.price200)})六、为事件处理函数标注类型原生 DOM 事件处理函数的参数默认会被推断为any类型没有任何类型提示。templateinputtypetextchangeinputChange//templatescriptsetuplangtsconstinputChange(e){// e 自动推断为 any 类型}/script想要有良好的类型提示我们需要手动标注类型事件处理函数的类型标注主要做两件事① 标注事件对象类型给事件对象形参e标注为Event类型可以获得事件对象的相关类型提示constinputChange(e:Event){// 获得事件对象的类型提示}② 使用断言获取更精确的类型如果需要更精确的 DOM 类型提示可以使用断言as进行操作constinputChange(e:Event){consttargete.targetasHTMLInputElement// 获取更精确的 DOM 类型}七、为模板引用标注类型7.1 如何进行类型标注通过具体的 DOM 类型联合null作为泛型参数。比如我们想获取一个inputDOM 元素templateinputrefinputRef//templatescriptsetuplangtsimport{ref,onMounted}fromvueconstinputRefrefHTMLInputElement|null(null)onMounted((){// 使用可选链防止类型错误inputRef.value?.focus()})/script说明泛型参数中通过将获取的 DOM 实际类型联合null进行类型标注组件完全挂载完毕之前 ref 的值都是null所以访问ref.value时需要使用可选链防止类型错误7.2 常见 DOM 元素类型元素类型TypeScript 类型divHTMLDivElementspanHTMLSpanElementinputHTMLInputElementbuttonHTMLButtonElementaHTMLAnchorElementformHTMLFormElementimgHTMLImageElement八、对象的非空值处理8.1 空值场景说明当对象的属性可能是null或undefined时我们称之为“空值”。直接访问空值上的属性或方法TypeScript 会报类型错误。比如inputRef在组件挂载完毕之前value还是null如果直接调用focus()TS 就会报错constinputRefrefHTMLInputElement|null(null)onMounted((){inputRef.value.focus()// ❌ 对象可能为 null})8.2 可选链方案推荐可选链?.是一种安全访问嵌套对象属性的方式。当可选链前面的值为undefined或null时它会停止运算并返回undefined不会报错constinputRefrefHTMLInputElement|null(null)onMounted((){inputRef.value?.focus()// 可选链安全访问})8.3 逻辑判断方案通过逻辑判断只有确认值存在时才继续访问属性constinputRefrefHTMLInputElement|null(null)onMounted((){if(inputRef.value){inputRef.value.focus()// 逻辑判断确认存在}})8.4 非空断言方案谨慎使用非空断言!用于告诉 TypeScript开发者明确知道当前的值一定不是null或undefined让 TS 通过类型校验constinputRefrefHTMLInputElement|null(null)onMounted((){inputRef.value!.focus()// 非空断言仅在确定有值时使用})⚠️注意使用非空断言要格外小心。它没有实际的 JS 判断逻辑只是通过了 TS 的类型校验。如果实际运行时值为null程序会直接报错。小结知识点示例说明ref 类型注解refUser | null(null)复杂数据用泛型指定类型reactive 类型注解reactiveState({ ... })类型不匹配时用泛型指定类型computed 类型注解computednumber(() ...)指定返回值类型事件处理函数e: Event标注事件对象类型获得类型提示模板引用refHTMLInputElement | null(null)为 DOM 元素添加类型约束可选链inputRef.value?.focus()安全访问可能为空的值非空断言inputRef.value!.focus()仅在确定值不为空时使用需谨慎参考资料Vue 3 官方文档 —— TypeScript 与组合式 API上一篇TypeScript 高级特性 —— 类型断言与泛型下一篇TypeScript 核心语法应用 —— Vue 3 中的使用下