Vue 3 搭配 TypeScript 与 Options API 时如何正确使用模板 ref
Options API 搭配 TypeScript 使用模板 ref 的最佳实践
行为说明
Vue 内置的默认类型定义中,Options API 暴露的 this.$refs 索引取值的推导结果为 unknown。在无提前类型配置的情况下,每次访问 ref 都需要手动书写类型断言(如 (this.$refs.myRef as HTMLElement))才能通过 TypeScript 校验,重复书写会带来较高的代码冗余。
零重复断言的实现方案
核心逻辑是通过 Vue 提供的全局类型扩展接口,一次性完成所有模板 ref 的类型映射,后续访问时无需重复断言:
- 第一步:在项目的全局类型声明文件(如
src/types/shims-vue.d.ts)中,扩展ComponentCustomProperties接口,逐一声明项目内所有模板 ref 对应的精确类型
代码示例:import { ComponentCustomProperties } from 'vue' declare module 'vue' { interface ComponentCustomProperties { $refs: { // 逐一声明项目内使用到的ref对应的实际类型 searchInput: HTMLInputElement confirmDialog: InstanceType<typeof ConfirmDialog> pageScrollWrap: HTMLElement } } } - 配置完成后的效果:所有组件内访问已声明的 ref 时,TypeScript 会自动推导对应类型,不需要再手动添加
as断言,比如直接书写this.$refs.searchInput.focus()就可以获得完整的类型提示和校验能力。
场景适配规则
- 动态 ref 场景:如果 ref 是通过
v-for循环绑定、或者会动态切换绑定的元素类型,只需要在声明时把对应 ref 的类型标注为匹配的数组类型或联合类型即可,比如formItemList: HTMLElement[]。 - 局部 ref 声明:如果不想把组件独有的 ref 类型放到全局声明文件中,也可以在对应组件文件内部通过局部模块扩展的方式补充类型定义,不会造成跨组件的全局类型污染。
方案特点
- 基于 Vue 原生类型扩展能力实现,不需要引入第三方类型补丁,版本兼容性强
- 一次声明即可在对应作用域内复用,完全消除重复的手动类型断言操作
- 类型校验强度和手动断言完全一致,不会降低代码安全边界
内容的提问来源于stack exchange,提问作者Fredrik
相关产品推荐
相关产品推荐

