Vue 3.3组件中如何基于multiple属性值条件约束modelValue的类型
Vue 3.3组件中如何基于multiple属性值条件约束modelValue的类型
这个需求完全可以实现!你提到的条件类型就是解决这个问题的核心,结合Vue 3.3的组件泛型能力,我们可以让modelValue的类型严格依赖于multiple的取值,下面一步步来修改你的组件:
第一步:调整组件的泛型参数
我们需要给组件新增一个泛型参数来约束multiple的字面量类型(而不是宽泛的boolean),这样TypeScript才能精准判断multiple是true还是false,进而约束modelValue的类型。修改后的组件脚本开头如下:
<script setup lang="ts" generic="T extends OptionProps, M extends boolean"> import { computed } from "vue"; import {OptionProps} from './types.ts'
第二步:用条件类型关联multiple和modelValue
接下来修改defineProps的类型定义,让modelValue的类型根据M(也就是multiple的字面量类型)动态变化:
const props = defineProps<{ options: T[]; multiple: M; // 当multiple为true时,modelValue必须是数组;为false时必须是单个T类型 modelValue: M extends true ? T[] : T; }>();
对应的emit也要同步调整,确保触发更新时的参数类型和modelValue一致:
const emit = defineEmits<{ "update:modelValue": [value: M extends true ? T[] : T]; }>();
第三步:同步更新computed的类型
最后修改proxy这个计算属性的setter参数类型,保持和上面的类型一致:
const proxy = computed({ get() { return props.modelValue; }, set(value: M extends true ? T[] : T) { emit("update:modelValue", value); }, });
效果验证
现在当父组件使用你的组件时,TypeScript会自动做类型校验:
- 如果设置
:multiple="false",但给model-value传了数组(比如你例子里的result),编辑器会直接抛出类型错误,提示你应该传入单个OptionProps类型的值; - 如果设置
:multiple="true",则model-value必须传入OptionProps[]类型的数组,否则也会报错。
举个正确的父组件使用例子:
<script setup lang="ts"> import { ref } from 'vue' import Comp from './Comp.vue'; import { OptionProps } from './types.ts' // 单个值的情况(对应multiple=false) const singleResult = ref<OptionProps>({id: 1, name: 'one'}) // 数组的情况(对应multiple=true) const multiResult = ref<OptionProps[]>([{id: 1, name: 'one'}, {id: 2, name: 'two'}]) </script> <template> <!-- 正确用法:multiple=false 对应单个值 --> <Comp :model-value="singleResult" :options="[{id: 1, name: 'one'}, {id: 2, name: 'two'}]" :multiple="false" /> <!-- 正确用法:multiple=true 对应数组 --> <Comp :model-value="multiResult" :options="[{id: 1, name: 'one'}, {id: 2, name: 'two'}]" :multiple="true" /> </template>
这样就完全实现了你想要的类型约束效果,父组件传参不符合规则时会立刻得到TypeScript的报错提示。
备注:内容来源于stack exchange,提问作者Yamit
相关产品推荐
相关产品推荐

