如何让Vue3的DataTable子组件继承父组件传入的数组类型?
问题描述
我定义了如下DataTable组件:
<script setup lang="ts"> defineProps({ rows: { type: Array, required: true }, columns: { type: Array as PropType<IColumn[]>, required: true } }); </script> <template> <tbody> <tr v-for="(row, i) in rows" :key="i"> <td v-for="column in columns" :key="column.name"> <slot :name="`cell.${column.name}`" :row="row" :value="row[column.name]" /> </td> </tr> </tbody> </template>
该组件的rows属性可接收任意类型数组,在component1和component2中分别传入MyOtherType[]和MyType[]类型的数组:
component1代码:
<script setup lang="ts"> defineProps({ myTypeArray: { type: Array as PropType<MyOtherType[]>, default: () => [] } }); </script> <template> <DataTable :rows="myTypeArray" :columns="[{ name: 'someOtherProperty' }]"> <template #cell.someOtherProperty="{ row }"> {{ row.someOtherProperty }} </template> </DataTable> </template>
component2代码:
<script setup lang="ts"> defineProps({ myTypeArray: { type: Array as PropType<MyType[]>, default: () => [] } }); </script> <template> <DataTable :rows="myTypeArray" :columns="[{ name: 'someProperty' }]"> <template #cell.someProperty="{ row }"> {{ row.someProperty }} </template> </DataTable> </template>
但DataTable组件将rows视为any[]类型,导致模板中使用row的属性时无法获得正确类型提示,只能通过类型断言处理。我希望无需在各处使用(row as MyType).someProperty这类写法,也不想通过枚举所有可能类型定义rows的PropType,而是想实现类似DataTable<T>的泛型组件,让rows的类型为PropType<T[]>,由父组件传入具体类型。请问是否可行?
解决方案
完全可行,Vue 3.3及以上版本支持泛型组件写法,可完美解决你的问题。具体实现如下:
1. 改造DataTable为泛型组件
通过<script setup>的generic声明泛型参数T,同时约束列的name必须是T的键,确保类型一致性:
<script setup lang="ts" generic="T"> import type { PropType } from 'vue'; // 定义列类型,确保name对应行数据的属性名 interface IColumn<T> { name: keyof T; // 可按需添加其他列配置,如label、width等 } defineProps<{ rows: T[]; columns: IColumn<T>[]; }>(); </script> <template> <tbody> <tr v-for="(row, i) in rows" :key="i"> <td v-for="column in columns" :key="column.name"> <slot :name="`cell.${column.name}`" :row="row" :value="row[column.name]" /> </td> </tr> </tbody> </template>
2. 父组件中使用(自动类型推导)
父组件无需额外配置,Vue会根据传入的rows自动推导泛型T的类型,模板中的row会直接获得对应类型的提示:
<script setup lang="ts"> import type { MyType } from './types'; defineProps({ myTypeArray: { type: Array as PropType<MyType[]>, default: () => [] } }); </script> <template> <DataTable :rows="myTypeArray" :columns="[{ name: 'someProperty' }]"> <template #cell.someProperty="{ row }"> <!-- row自动具备MyType的类型提示,无需断言 --> {{ row.someProperty }} </template> </DataTable> </template>
3. 显式指定泛型(可选)
若遇到类型推导失效的场景,可直接在使用组件时显式声明泛型类型:
<DataTable<MyType> :rows="myTypeArray" :columns="[{ name: 'someProperty' }]"> <template #cell.someProperty="{ row }"> {{ row.someProperty }} </template> </DataTable>
注意事项
- 需确保Vue版本≥3.3,且项目TypeScript配置开启
strict模式(tsconfig.json中compilerOptions.strict: true),以获得最佳类型提示效果。
内容的提问来源于stack exchange,提问作者Sabrina B.
相关产品推荐
相关产品推荐

