Vue+TypeScript中如何正确标注Ref对象的键类型?
TypeScript + Vue响应式对象键类型标注问题解决
问题场景
我定义了如下响应式对象类型与实例:
type Players = Ref<{ 1: Player, 2: Player }> const players: Players = ref({ 1: { id: 1, name: 'Player 1', questionIds: [], modifierIds: [] }, 2: { id: 2, name: 'Player 2', questionIds: [], modifierIds: [] } })
希望为选中的对象键activePlayerId标注类型,尝试了两种写法:
const activePlayerId = ref<keyof Players>(1)
const activePlayerId = ref<keyof Ref<Players>>(1)
但都触发错误:TS2345: Argument of type '1' is not assignable to parameter of type 'keyof Players'.,请问如何正确标注类型?
解决方案
你的问题出在Players类型本身是Ref包裹的对象,直接用keyof Players取到的是Ref接口的内置键(比如value、_isRef),而非你需要的内部玩家对象的键。以下两种方法可以解决:
方法1:拆分类型定义
先单独定义内部玩家对象的类型,再基于它创建Players的Ref类型,这样直接取内部类型的键即可:
// 先定义玩家映射的基础类型 type PlayerMap = { 1: Player, 2: Player } // 基于基础类型创建Ref类型 type Players = Ref<PlayerMap> const players: Players = ref({ 1: { id: 1, name: 'Player 1', questionIds: [], modifierIds: [] }, 2: { id: 2, name: 'Player 2', questionIds: [], modifierIds: [] } }) // 直接使用PlayerMap的键类型 const activePlayerId = ref<keyof PlayerMap>(1)
方法2:使用Vue内置工具类型提取内部类型
如果不想拆分类型,可以用Vue提供的UnwrapRef工具类型,提取Ref包裹的原始对象类型,再取它的键:
import type { UnwrapRef } from 'vue' // 保留原Players类型定义 type Players = Ref<{ 1: Player, 2: Player }> const players: Players = ref({ 1: { id: 1, name: 'Player 1', questionIds: [], modifierIds: [] }, 2: { id: 2, name: 'Player 2', questionIds: [], modifierIds: [] } }) // 提取Ref内部的对象类型后再取键 const activePlayerId = ref<keyof UnwrapRef<Players>>(1)
原理说明
keyof Players实际获取的是Ref接口的属性键,和你需要的玩家ID键完全不匹配,因此触发类型错误。UnwrapRef<T>是Vue专门用于解构Ref包装类型的工具,能直接拿到Ref内部的原始值类型,这样keyof UnwrapRef<Players>就能正确得到1 | 2这个符合需求的键类型。
内容的提问来源于stack exchange,提问作者Miguel Stevens
相关产品推荐
相关产品推荐

