在 Vue 3 + TypeScript 中,ref 需用泛型显式标注类型(如 ref<number>),reactive 应传入带接口定义的对象字面量;解构 reactive 必须用 toRefs 保留响应性与类型,禁用 reactive 包裹基本类型或 ref 初始化 null/undefined 不标注联合类型。

在 Vue 3 + TypeScript 的 Composition API 中,为 ref 和 reactive 正确标注类型不是可选项,而是保障类型安全、避免运行时错误的关键步骤。类型写得准,IDE 能自动补全、编译器能提前报错、重构也更放心。
ref 的类型标注方式
ref 接收一个初始值,返回 Ref<t></t> 类型的对象,.value 的类型就是你传入值的类型 —— 但显式标注能增强可读性和泛型推导可靠性。
- 基础写法:用泛型直接声明,最清晰
const count = ref
const name = ref
const isActive = ref
- 对象类型 ref:建议用接口或类型别名明确结构
interface User { id: number; name: string; email?: string }
const user = ref
- 可选值或联合类型需注意:TS 会自动推导,但复杂场景建议显式写
const status = ref('loading')
reactive 的类型标注方式
reactive 只接受对象或数组,它本身不接受泛型参数,但 TypeScript 会根据传入对象的字面量类型自动推导。要获得完整类型提示,推荐配合接口使用。
立即学习“前端免费学习笔记(深入)”;
- 直接传入带类型的对象字面量(推荐)
interface FormState {
username: string;
password: string;
remember: boolean;
}
const form = reactive
username: '',
password: '',
remember: false
})
- 避免只用 {} 或 any:否则失去类型约束和 IDE 支持
- 嵌套对象无需额外操作:reactive 天然深度响应,类型也会递归推导
组合场景下的类型处理技巧
实际开发中常遇到混合使用、解构、异步数据等情形,类型需同步适配。
- 解构 reactive 对象时,必须用
toRefs才能保留响应性和类型
const state = reactive({ count: 0, title: 'Vue' })
const { count, title } = toRefs(state) // count 是 Ref
- ref 包裹对象后修改属性:访问
.value.xxx,类型由 ref 泛型保证
const config = ref({
apiUrl: 'https://api.example.com',
timeout: 5000
})
config.value.timeout = 8000 // 类型安全,IDE 可提示
- 函数返回 ref/ reactive:在函数签名中明确返回类型,便于复用
function useCounter(initial = 0): { count: Ref
const count = ref(initial)
const increment = () => count.value++
return { count, increment }
}
常见类型陷阱与规避方法
类型写错往往不会立刻报错,但会在后续调用中暴露问题。
- ❌ 不要对基本类型用 reactive:TS 编译会报错,运行时也无响应
const num = reactive(42) // ❌ TS error: Argument of type 'number' is not assignable to parameter of type 'object'
- ❌ ref 初始化 null/undefined 时,需用联合类型并启用 strictNullChecks
const el = ref
- ❌ reactive 解构不加 toRefs:类型看似存在,但实际丢失响应性,且 .value 不存在
const { count } = reactive({ count: 0 }) // ❌ count 是 number,非 Ref,无法响应


















