I want to extend a component with React/TS (in my case is @mui/x-data-grid DataGrid) to fill the classes
prop with my own app classes.
The way I first tought was to create a component, for example CustomDataGrid, like this:
import React from 'react';
import {DataGrid} from '@mui/x-data-grid';
const CustomDataGrid = (props) => {
return <DataGrid {...props} classes={{root: 'my-root-class'}} />;
};
export default CustomDataGrid;
The problem is that I'm using typescript and I want to maintain the type ability to autocomplete in the IDE.
I also tried to define the type of my component as React.FC< Props>, but take a look at the DataGrid code:
declare const DataGrid: React$1.MemoExoticComponent<React$1.ForwardRefExoticComponent<Omit<Partial<DataGridPropsWithDefaultValues> & DataGridPropsWithComplexDefaultValueBeforeProcessing & DataGridPropsWithoutDefaultValue, DataGridForcedPropsKey> & {
pagination?: true | undefined;
} & React$1.RefAttributes<HTMLDivElement>>>;
I don't know what to fill in the generic arguments to type the props.
Does anyone have an idea of how to do this without losing the autocomplete feature?
CodePudding user response:
You can do that by using the React.ComponentProps
¹ utility type to get the type of the props of DataGrid
, and TypeScript's Omit
to remove classes
from it:
import React from "react";
import {DataGrid} from "@mui/x-data-grid";
const CustomDataGrid = (props: Omit<React.ComponentProps<typeof DataGrid>, "classes">) => {
return <DataGrid {...props} classes={{root: "my-root-class"}} />;
};
Here's a breakdown of Omit<Parameters<typeof DataGrid>[0], "classes">
:
typeof DataGrid
gets the type ofDataGrid
(this is TypeScript'stypeof
, not JavaScript's which would just give us"function"
).React.ComponentProps<...>
gives us a tuple type with the types of the parameters of the function in order.Omit<..., "classes">
removes theclasses
type from it, since you're hardcoding that and presumably don't want people to specify it when usingCustomDataGrid
.
If that last bullet point isn't accurate and you do want to allow people to specify classes, you can remove the Omit<..., "classes">
part, but be sure in that case to combine any props.classes
specified by the caller with your hardcoded ones; the code as it is now would override theirs with yours. For instance, something like:
const myRootClass = "my-root-class";
const CustomDataGrid = (props: React.ComponentProps<typeof DataGrid>) => {
const classes = props.classes ?? {};
if (classes.root) {
classes.root = ` ${myRootClass}`;
} else {
classes.root = myRootClass;
}
return <DataGrid {...props} classes={classes} />;
};
¹ There's a note in the inline documentation of ComponentProps
saying:
NOTE: prefer
ComponentPropsWithRef
, if the ref is forwarded, orComponentPropsWithoutRef
when refs are not supported.
...so you may want the appropriate one of those instead of ComponentProps
itself.