使用 reactive 时必须用泛型(如 reactive())而非类型注解,因其返回 unwrapnestedrefs 类型;interface 应显式标注可选、只读、联合类型等语义;对象数组和默认值对象需明确泛型约束以保类型安全。

用 reactive 时写 interface 不是“套一层就行”,关键在于类型声明方式必须匹配其返回值的代理特性——不能直接用类型注解(: DialogOption),而要用泛型传入(reactive<dialogoption>()</dialogoption>)。
必须用泛型,不能用类型注解
reactive() 返回的是 UnwrapNestedRefs<t></t> 类型,不是原始接口类型。如果写成:
-
❌ 错误写法:
const dialog: DialogOption = reactive({ visible: false, title: '提示' }) -
✅ 正确写法:
const dialog = reactive<dialogoption>({ visible: false, title: '提示' })</dialogoption>
前者会报错:类型不兼容;后者让 TypeScript 精准推导出响应式代理后的字段可读可写、嵌套属性也保持响应式。
interface 定义要兼顾结构与语义
接口本身要清晰表达数据意图,比如可选、只读、联合类型等都应显式标注:
- 用
?标明可选字段(如description?: string) - 用
readonly标明不应被修改的字段(如readonly id: number) - 对固定取值用字面量联合类型(如
status: 'loading' | 'success' | 'error') - 嵌套对象也建议单独抽离 interface,避免内联过深
数组和对象数组的 reactive 类型写法
不要写 reactive([]) 或 reactive({}) 让 TS 盲猜——推断结果常为 any[] 或 Record<string unknown></string>,失去约束:
- 对象数组:
const list = reactive<user>([])</user> - 带默认值的对象:
const form = reactive<loginform>({ username: '', password: '' })</loginform> - 空初始化但需强类型:
const config = reactive<appconfig>({ apiUrl: '', timeout: 5000 })</appconfig>
配合 computed 和 watch 时的类型延续性
从 reactive 衍生的计算属性或监听目标,类型会自然继承:
-
const visible = computed(() => dialog.visible)→ 类型是ReadonlyRef<boolean></boolean> -
watch(() => dialog.title, (newVal) => {...})→newVal类型是string - 不需要额外断言,前提是 reactive 本身用了泛型约束
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











