Help making type-safe table component with generic, defineSlots, and withDefaults #8851
Unanswered
vincerubinetti
asked this question in
Help/Questions
Replies: 2 comments 3 replies
-
https://github.com/Shyam-Chen/Vue-Starter/blob/main/src/components/Table.vue <script lang="ts" setup generic="T extends object">
import type { VNode } from 'vue';
import { reactive, watch, toRef } from 'vue';
import omit from 'lodash/omit';
import ProgressBar from './ProgressBar.vue';
import Button from './Button.vue';
import Select from './Select.vue';
import Checkbox from './Checkbox.vue';
const props = defineProps<{
columns?: Array<{
key: string;
name: string;
sticky?: string;
sortable?: boolean;
spanable?: boolean;
}>;
rows?: T[];
count?: number;
stickyHeader?: boolean;
selectable?: boolean;
selected?: T[];
loading?: boolean;
}>();
const emit = defineEmits<{
(evt: 'update:selected', val: T[]): void;
(evt: 'change', val: { rows?: number; page?: number; field?: string; direction?: string }): void;
}>();
defineSlots<{
thead(props: {}): VNode;
[colKey: string]: (props: { row: T }) => VNode;
spanable(props: {}): VNode;
}>();
</script> |
Beta Was this translation helpful? Give feedback.
1 reply
-
Going to selfishly tag @mattpocock to see if he knows the answer to this. TL;DR: // table React/Vue component
type Props<Datum extends object> = {
cols: {
// key of row object to access as value
key: keyof Datum;
// custom render function for cell
render?: (cell: NoInfer<Datum[keyof Datum]>) => ReactNode;
}[];
rows: Datum[];
}; // usage in React/Vue template
<Table
cols={[
{
key: "name",
},
{
key: "money",
render: (cell) => <div>{(cell as number).toLocaleString()}</div>,
// can we avoid casting here? can we get cell type from passed rows?
// i'm willing to restructure things significantly to accommodate this
},
]}
rows={[
{ name: "Jane", money: 1234567 },
{ name: "John", money: 7654321 },
]}
/> |
Beta Was this translation helpful? Give feedback.
2 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
I'm trying to make a generic table component that the rest of my team, who are not frontend developers, can use easily, and have it provide helpful type hints and safety based on the column and row data passed in. At the moment, I'm just using
any
for types inside the component, and type assertions where using it, which is not great.Some of this is TypeScript difficulty, some of it is issues with the new Vue 3.3 features. I think it's probably an inherently hard problem, but libraries like TanStack Table do it somehow. I'm not sure how they do it under the hood, and it might not be as ergonomic as I need it, but they do it.
Insights on how to solve any of my issues or recommendations for better approaches would be greatly appreciated.
What I want
The ideal usage of the component, with minimal configuration by the "consumer". The comments list the goals I'm trying to achieve.
What I've tried
How I think it would be implemented, and the issues I run into. Some comments show the type errors I get.
Relevant discussion: vuejs/rfcs#436
Beta Was this translation helpful? Give feedback.
All reactions