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
相关产品推荐
相关产品推荐

