Vue中如何不使用交集类型从元组数组动态定义ButtonProps类型?
问题背景
你原本通过以下TypeScript代码动态定义了Button组件的props类型:
const intents = ["primary", "secondary", "accent", "danger"] as const; const buttonSizes = ["small", "medium", "big"] as const; type IntentType = (typeof intents)[number]; type SizeType = (typeof buttonSizes)[number]; type ButtonProps = { intent?: IntentType; size?: SizeType; } & { [K in IntentType as `${Lowercase<K>}`]?: boolean; };
但Vue会抛出错误:
Internal server error: [@vue/compiler-sfc] type argument passed to defineProps() must be a literal type, or a reference to an interface or literal type.
静态定义的方式虽可行,但会导致后续遍历intents时出现重复代码,因此需要一种既保留动态生成属性、又不使用交集类型的方案。
可行方案:使用接口扩展替代交集类型
Vue的编译器允许将接口作为defineProps的类型参数,因此可以将动态生成的属性类型与基础props类型通过接口扩展的方式合并,避免直接使用交集类型:
const intents = ["primary", "secondary", "accent", "danger"] as const; const buttonSizes = ["small", "medium", "big"] as const; type IntentType = (typeof intents)[number]; type SizeType = (typeof buttonSizes)[number]; // 先定义动态生成的intent标记属性类型 type IntentFlags = { [K in IntentType as `${Lowercase<K>}`]?: boolean; }; // 通过接口扩展合并基础props与动态属性 interface ButtonProps extends IntentFlags { intent?: IntentType; size?: SizeType; }
在Vue组件中使用时,直接将ButtonProps传入defineProps即可:
<script setup lang="ts"> // ...上述类型定义 const props = defineProps<ButtonProps>(); </script>
这种方式既保留了动态生成属性的能力(无需重复写primary?/secondary?等属性),又符合Vue编译器对defineProps类型参数的要求,同时后续遍历intents数组时也不会出现重复代码。
内容的提问来源于stack exchange,提问作者Demiro-FE-Architect
相关产品推荐
相关产品推荐

