必须用泛型而非类型注解为 reactive 对象指定类型,因 reactive 返回 unwrapnestedrefs 类型,直接注解会导致类型不兼容;接口需完整描述结构,嵌套对象也只需顶层泛型。

在 TypeScript 中为 reactive 对象显式指定强类型接口,关键不是“能不能加”,而是“怎么加才既安全又不破坏响应式行为”。直接用类型注解赋值会出错,必须匹配 reactive 的实际返回类型。
必须用泛型,不能用类型注解
reactive() 返回的不是原始对象类型,而是 UnwrapNestedRefs<t></t> 类型。如果你写成:
// ❌ 错误:类型不兼容
const state: UserState = reactive({ name: 'Alice', age: 30 });
TypeScript 会报错,因为左侧是 UserState,右侧是 UnwrapNestedRefs,二者结构不同。
Orderly React SDK 钩子使用参考指南,包括 useOrderEntry、usePositionStream、useOrderbookStream、useCollateral 等。
✅ 正确写法是把类型作为泛型参数传入:
-
定义接口:
interface UserState { name: string; age: number; } -
调用时传泛型:
const state = reactive<userstate>({ name: 'Alice', age: 30 });</userstate> - 此时
state的类型是UnwrapNestedRefs<userstate></userstate>,属性访问、修改、响应式更新全部有完整类型提示
深层嵌套对象也要统一用泛型
如果对象含嵌套 ref 或 reactive 层级(比如 user.profile.address),依然只需顶层泛型:
- 接口需描述完整形状:
interface Address { city: string; zip?: string; }interface Profile { address: Address; }interface UserState { name: string; profile: Profile; } - 创建时仍只传最外层泛型:
const user = reactive<userstate>({ name: 'Bob', profile: { address: { city: 'Shanghai' } } });</userstate> - TypeScript 会自动推导所有嵌套层级的类型,无需额外标注
避免无泛型的松散写法
像 const state = reactive({}) 这种写法会导致后续添加属性时失去类型检查和编辑器提示:
- 初始空对象 → 推断为
Record<string unknown></string> - 之后写
state.count = 1,不会报错,但state.count.toFixed()会提示“类型上不存在 toFixed” - 重构困难:改接口字段名时,TypeScript 不会帮你找出所有使用点
所以哪怕对象结构简单,也建议始终显式传泛型,哪怕只是 reactive(...)。
与 ref 的区别要分清
ref 支持泛型和类型注解两种方式(如 ref<number>(0)</number> 或 const count: Ref<number> = ref(0)</number>),但 reactive 只推荐泛型方式。
- 泛型方式:类型精准、语义清晰、与 Vue 响应式机制对齐
- 类型注解方式:强制类型转换易掩盖问题,且无法覆盖
UnwrapNestedRefs的代理特性 - 尤其注意不要混用:
reactive<userstate>(...)</userstate>是标准做法;const s: UserState = reactive(...)是典型错误









