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

如何让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.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 21:15:35