I am creating a CustomColumn interface definition like this:
export interface CustomColumn<T extends object> extends Column<T> {
width?: string;
}
and then using a hook to generate columns:
export const useOverviewColumns = (): CustomColumn<OverviewTableData>[] => { ...etc
OverviewTableData defines my data.
I also have some CSS styles that I'm using in the columns:
` const generalCellStyles: React.CSSProperties = {
fontSize: "1.4rem",
color: theme.palette.grey[300],
};
const alignCenter: React.CSSProperties = {
textAlign: "center",
};
`
and I use these like this:
{
title: "Internal Fund Name",
field: "internalFundName",
cellStyle: {
...generalCellStyles,
},
width: "11%",
},
However, when I go to use the columns, Typescript throws this error:
Type 'CSSProperties | ((data: OverviewTableData[], rowData: OverviewTableData) => CSSProperties) | undefined' is not assignable to type 'CSSProperties | ((data: object[], rowData: object) => CSSProperties) | undefined'.
Type '(data: OverviewTableData[], rowData: OverviewTableData) => CSSProperties' is not assignable to type 'CSSProperties | ((data: object[], rowData: object) => CSSProperties) | undefined'.
Type '(data: OverviewTableData[], rowData: OverviewTableData) => CSSProperties' is not assignable to type '(data: object[], rowData: object) => CSSProperties'.
Types of parameters 'data' and 'data' are incompatible.
Type 'object[]' is not assignable to type 'OverviewTableData[]'.
I am clearly specifying that my CustomColumn extends object, so I don't see what the issue is. It would be great if someone could help.
To anyone else having trouble with this, React.memo was the cause, it was messing up a generic declaration
I'm getting a similar error. I want to define a custom table that takes in the same props as the MaterialTable:
export interface CustomTableProps<T extends object> extends MaterialTableProps<T> {}
And I want it to take all kinds of row data.
So I instantiate it like this:
export interface RecentMeasurementsTableProps extends Omit<CustomTableProps<StatisticReport>, 'data' | 'columns'> {}
And define my columns as such:
const columns: Column<StatisticReport>[] = [];
And when I use <CustomTable columns={columns}>, I get:
Type 'Column<StatisticReport>[]' is not assignable to type 'Column<object>[]'.
Type 'Column<StatisticReport>' is not assignable to type 'Column<object>'.
Types of property 'cellStyle' are incompatible.
Type 'CSSProperties | ((data: StatisticReport[], rowData: StatisticReport) => CSSProperties) | undefined' is not assignable to type 'CSSProperties | ((data: object[], rowData: object) => CSSProperties) | undefined'.
Type '(data: StatisticReport[], rowData: StatisticReport) => CSSProperties' is not assignable to type 'CSSProperties | ((data: object[], rowData: object) => CSSProperties) | undefined'.
Type '(data: StatisticReport[], rowData: StatisticReport) => CSSProperties' is not assignable to type '(data: object[], rowData: object) => CSSProperties'.
Types of parameters 'data' and 'data' are incompatible.
Type 'object[]' is not assignable to type 'StatisticReport[]'.
Type 'object' is not assignable to type 'StatisticReport'.ts(2322)
index.d.ts(7, 3): The expected type comes from property 'columns' which is declared here on type 'IntrinsicAttributes & CustomTableProps<object> & { children?: ReactNode; }'
Any idea?
@slhck How are you actually using your custom component? What worked for me was I made a component called CustomTable and then called
<CustomTable<MyDataObjectInterface> {...props} />
Post your code if you want me to have a look because I solved this exact problem on Friday
I have a custom table:
export interface CustomTableProps<T extends object> extends MaterialTableProps<T> {
}
const CustomTable: React.FC<CustomTableProps<object>> = (
props: CustomTableProps<object> = {
data: [],
columns: [],
},
): JSX.Element => {
return (
<MaterialTable
options={{
filtering: false,
search: false,
toolbar: false,
}}
{...props}
/>
);
};
export default CustomTable;
And when I want to use it:
export interface RecentMeasurementsTableProps extends Omit<CustomTableProps<StatisticReport>, 'data' | 'columns'> {
extended?: boolean;
}
const RecentMeasurementsTable: React.FC<RecentMeasurementsTableProps> = (
props: RecentMeasurementsTableProps = { extended: false },
): JSX.Element => {
const columns: Column<StatisticReport>[] = [
// ...
];
const data = [
// ...
]
if (props.extended) {
// other stuff
}
return <CustomTable columns={columns} data={data} />;
};
I notice that I did not actually use generics for creating <CustomTable> ...
I think I got it. Define the custom table as generic (see this):
import React, { forwardRef } from 'react';
import AddBox from '@material-ui/icons/AddBox';
import ArrowDownward from '@material-ui/icons/ArrowDownward';
import Check from '@material-ui/icons/Check';
import ChevronLeft from '@material-ui/icons/ChevronLeft';
import ChevronRight from '@material-ui/icons/ChevronRight';
import Clear from '@material-ui/icons/Clear';
import DeleteOutline from '@material-ui/icons/DeleteOutline';
import Edit from '@material-ui/icons/Edit';
import FilterList from '@material-ui/icons/FilterList';
import FirstPage from '@material-ui/icons/FirstPage';
import LastPage from '@material-ui/icons/LastPage';
import Remove from '@material-ui/icons/Remove';
import SaveAlt from '@material-ui/icons/SaveAlt';
import Search from '@material-ui/icons/Search';
import ViewColumn from '@material-ui/icons/ViewColumn';
import MaterialTable, { MaterialTableProps, Options, Icons } from 'material-table';
// Set the table icons directly from Material-UI, see https://github.com/mbrn/material-table/issues/1004#issuecomment-525274793
const tableIcons: Icons = {
// eslint-disable-next-line react/display-name
Add: forwardRef((props, ref) => <AddBox {...props} ref={ref} />),
// eslint-disable-next-line react/display-name
Check: forwardRef((props, ref) => <Check {...props} ref={ref} />),
// eslint-disable-next-line react/display-name
Clear: forwardRef((props, ref) => <Clear {...props} ref={ref} />),
// eslint-disable-next-line react/display-name
Delete: forwardRef((props, ref) => <DeleteOutline {...props} ref={ref} />),
// eslint-disable-next-line react/display-name
DetailPanel: forwardRef((props, ref) => <ChevronRight {...props} ref={ref} />),
// eslint-disable-next-line react/display-name
Edit: forwardRef((props, ref) => <Edit {...props} ref={ref} />),
// eslint-disable-next-line react/display-name
Export: forwardRef((props, ref) => <SaveAlt {...props} ref={ref} />),
// eslint-disable-next-line react/display-name
Filter: forwardRef((props, ref) => <FilterList {...props} ref={ref} />),
// eslint-disable-next-line react/display-name
FirstPage: forwardRef((props, ref) => <FirstPage {...props} ref={ref} />),
// eslint-disable-next-line react/display-name
LastPage: forwardRef((props, ref) => <LastPage {...props} ref={ref} />),
// eslint-disable-next-line react/display-name
NextPage: forwardRef((props, ref) => <ChevronRight {...props} ref={ref} />),
// eslint-disable-next-line react/display-name
PreviousPage: forwardRef((props, ref) => <ChevronLeft {...props} ref={ref} />),
// eslint-disable-next-line react/display-name
ResetSearch: forwardRef((props, ref) => <Clear {...props} ref={ref} />),
// eslint-disable-next-line react/display-name
Search: forwardRef((props, ref) => <Search {...props} ref={ref} />),
// eslint-disable-next-line react/display-name
SortArrow: forwardRef((props, ref) => <ArrowDownward {...props} ref={ref} />),
// eslint-disable-next-line react/display-name
ThirdStateCheck: forwardRef((props, ref) => <Remove {...props} ref={ref} />),
// eslint-disable-next-line react/display-name
ViewColumn: forwardRef((props, ref) => <ViewColumn {...props} ref={ref} />),
};
export interface CustomTableProps<T extends object> extends MaterialTableProps<T> {
rowsPerPage?: number;
}
/**
* Render a custom Material UI table, including all necessary icons.
*
* By default, no filtering, search, or toolbar is enabled.
* All props are passed to the Material table itself.
*
* See https://material-table.com/#/ for more
*/
const CustomTable: <T extends object>(props: CustomTableProps<T>) => JSX.Element = <T extends object>({
rowsPerPage = 10,
...props
}: CustomTableProps<T>) => {
const options: Options = Object.assign(props.options || {}, {
filtering: false,
search: false,
toolbar: false,
pageSize: rowsPerPage,
pageSizeOptions: [5, 25, 50, 100],
});
return <MaterialTable icons={tableIcons} options={options} {...props} />;
};
export default CustomTable;
Then instantiate it like this, where you pass the actual column type and any other props you may want to forward:
<CustomTable<SomeType> columns={columns} data={data} {...props} />
That's it, glad you solved.
Perhaps you want to close this issue if you solved it?
Closing this issue out. Please reopen if needed.
Most helpful comment
I think I got it. Define the custom table as generic (see this):
Then instantiate it like this, where you pass the actual column type and any other props you may want to forward: