在文件中我们通过 ref 来获取组件实例,如:
<template>
<a-input ref="inputRef" placeholder="输入" />
<a-button @click="onClick">点击</a-button>
</template>
<script lang="ts" setup>
import { ref, onMounted } from 'vue'
const inputRef = ref()
const onClick = () => {
inputRef.value.focus()
}
</script>
这里我们调用 inputRef.value.focus(),代码提示不会报错,因为 input.vue 类型此时是 any。但也因此我们无法获取类型提示,此时我们就可以给 ref 加上类型。

这是因为 ref 在参数留空的情况下,返回值类型是Ref<T | undefined>,为了避免我们在组件还没有挂载或者已经被销毁之后去使用组件的实例,如果组件未挂载或组件已销毁,它的值当然应该是undefined。
# 容错判断或可选链
const onClick = () => {
if (inputRef.value) {
inputRef.value.focus()
}
}
// 或者
const onClick = () => {
inputRef.value?.focus()
}
但是当我们想要获取实例上的某个属性,还是需要做非空判断,因为本质上我们可能获取到的值还是 undefined。
# 类型断言
const inputRef = ref<HTMLInputElement>() as Ref<HTMLInputElement>
const onClick = () => {
inputRef.value.disabled
}
针对自定义组件,我们可以使用 TS 的内置工具来获取类型。
type IType = InstanceType<typeof 组件>
# 封装获取实例类型
我们可以针对内置属性封装一个自己函数,避免每次都做类型断言。
import { Component, Ref, ref } from 'vue'
export const useInstance = <T extends abstract new (...args: any[]) => Component>() => ref() as Ref<InstanceType<T>>
/**
* @description 使用 useInstance 获取组件实例类型
*/
<script lang="ts" setup>
import { useInstance } from '@/hooks/useInstance'
const inputRef = useInstance<typeof HTMLInputElement>()
const onClick = () => {
inputRef.value.disabled
}
</script>
# 注意
TypeScript 提供了 “类型断言” 这样一种手段,允许开发者在代码中 “断言” 某个值的类型,告诉编译器此处的值是什么类型。TypeScript 一旦发现存在类型断言,就不再对该值进行类型推断,而是直接采用断言给出的类型。
这种做法的实质是,允许开发者在某个位置 “绕过” 编译器的类型推断,让本来通不过类型检查的代码能够通过,避免编译器报错。这样虽然削弱了 TypeScript 类型系统的严格性,但是为开发者带来了方便,毕竟开发者比编译器更了解自己的代码。
总之,类型断言并不是真的改变一个值的类型,而是提示编译器,应该如何处理这个值。在我们无法确定当前的变量类型时,还是需要做非空判断,保证我们代码的准确性。