You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue中如何使用Enum作为组件属性传递的键类型?

解决Vue中枚举作为对象键传递后无法识别的问题

问题场景

我用字符串枚举定义了选项键,父组件基于该枚举创建对象并传递给子组件,但子组件中尝试通过枚举成员名访问对象属性时,TypeScript报错:Property 'randSize' does not exist on type '{ randomSized: number | boolean; ... }'.ts(2339)

相关代码:

枚举定义(util.ts)

export enum Options {
  randSize = 'randomSized',
  timer = 'showTimer',
  randAngle = 'randomAngle',
  colours = 'multiColour',
  cardSize = 'cardSize',
  numCards = 'numCards'
}

父组件代码

import { Options} from './util'
let options : {[key in Options]: number | boolean} = {
  [Options.randSize]: true,
  [Options.timer] : false,
  [Options.randAngle] : true,
  [Options.colours] : true,
  [Options.cardSize] : 8,
  [Options.numCards] : 20
}

function changeOption( option: string, value: number | boolean) {
  options = {...options,[option]:value}
}

子组件代码

import { ref, onMounted } from 'vue'
import { Options} from '../util'

const props = defineProps<{
  options: {[key in Options]: number | boolean}
}>()

onMounted(() =>{
  console.log(props.options);
  let foo = props.options.randSize; // 此处报错
})

错误原因

你使用的是字符串枚举,Options.randSize的实际值是字符串'randomSized',因此父组件创建的对象的键是'randomSized',而非枚举成员名'randSize'。子组件里用props.options.randSize访问时,自然找不到对应的属性。

解决方案

方案一:通过枚举值访问对象属性(最直接)

子组件中不要直接用枚举成员名,而是用枚举值作为键来访问属性:

onMounted(() =>{
  console.log(props.options);
  let foo = props.options[Options.randSize]; // 正确访问
})

同时建议优化父组件的changeOption函数参数类型,避免传入无效字符串:

function changeOption( option: Options, value: number | boolean) {
  options = {...options,[option]:value}
}

方案二:改用数字枚举(适合不需要特定字符串键的场景)

如果业务不需要用指定字符串作为对象键,可以将枚举改为数字枚举,此时对象的键会对应枚举成员名:

// 修改util.ts中的枚举定义
export enum Options {
  randSize,
  timer,
  randAngle,
  colours,
  cardSize,
  numCards
}

之后父组件和子组件中就可以直接用props.options.randSize访问属性,但注意此时对象的键是数字(0、1、2...),而非原来的字符串。

方案三:创建反向映射(保留字符串键+支持成员名访问)

如果需要同时保留原来的字符串键,又想通过枚举成员名访问,可以在util.ts中添加反向映射:

export enum Options {
  randSize = 'randomSized',
  timer = 'showTimer',
  randAngle = 'randomAngle',
  colours = 'multiColour',
  cardSize = 'cardSize',
  numCards = 'numCards'
}

// 创建反向映射对象,通过枚举成员名获取对应的字符串键
export const OptionKeys = Object.fromEntries(
  Object.entries(Options).filter(([key]) => isNaN(Number(key)))
) as {[K in keyof typeof Options]: Options[K]};

// 定义选项对象的类型别名
export type OptionsObject = {[key in Options]: number | boolean};

然后子组件中可以这样访问:

import { ref, onMounted } from 'vue'
import { Options, OptionKeys, OptionsObject } from '../util'

const props = defineProps<{
  options: OptionsObject
}>()

onMounted(() =>{
  console.log(props.options);
  let foo = props.options[OptionKeys.randSize]; // 通过反向映射访问
})

内容的提问来源于stack exchange,提问作者quilkin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 01:17:21