New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[data grid] Why is GridValueFormatter defaulting the value to never? #12914
Comments
@j3ski-bioraptor thanks for raising this. Here is diff for changing the diff --git a/packages/x-data-grid/src/models/colDef/gridColDef.ts b/packages/x-data-grid/src/models/colDef/gridColDef.ts
index 36d7619a5..f22ee3291 100644
--- a/packages/x-data-grid/src/models/colDef/gridColDef.ts
+++ b/packages/x-data-grid/src/models/colDef/gridColDef.ts
@@ -57,7 +57,7 @@ export type GridValueFormatter<
R extends GridValidRowModel = GridValidRowModel,
V = any,
F = V,
- TValue = never,
+ TValue = unknown,
> = (
value: TValue,
row: R, Any objections @mui/xgrid ? |
In v6 of the Data Grid, the // TS should complain here, the first argument in v7 is the `value` itself, not the `params` object
valueFormatter: (params) => params.value, The decision to use We didn't use valueFormatter: (value: string, row) => value.toUpperCase(), It's a trade-off that made sense to me at that time. |
OK, @cherniavskii this took me a while, but I think I might have a solution for this: diff --git a/packages/x-data-grid/src/models/colDef/gridColDef.ts b/packages/x-data-grid/src/models/colDef/gridColDef.ts
index 36d7619a5..25066688c 100644
--- a/packages/x-data-grid/src/models/colDef/gridColDef.ts
+++ b/packages/x-data-grid/src/models/colDef/gridColDef.ts
@@ -23,6 +23,21 @@ export type GridAlignment = 'left' | 'right' | 'center';
export type ValueOptions = string | number | { value: any; label: string } | Record<string, any>;
+type ValueMap = {
+ number: number;
+ string: string;
+ date: Date;
+ dateTime: Date;
+ boolean: boolean;
+ actions: never;
+ singleSelect: ValueOptions;
+ custom: never;
+};
+
+type ValueBasedType<T extends GridColType | undefined> = T extends GridColType
+ ? ValueMap[T]
+ : never;
+
/**
* Value that can be used as a key for grouping rows
*/
@@ -170,35 +185,10 @@ export interface GridBaseColDef<R extends GridValidRowModel = GridValidRowModel,
* @returns {GridComparatorFn<V>} The comparator function to use.
*/
getSortComparator?: (sortDirection: GridSortDirection) => GridComparatorFn<V> | undefined;
- /**
- * The type of the column.
- * @default 'string'
- * @see See {@link https://mui.com/x/react-data-grid/column-definition/#column-types column types docs} for more details.
- */
- type?: GridColType;
/**
* Allows to align the column values in cells.
*/
align?: GridAlignment;
- /**
- * Function that allows to get a specific data instead of field to render in the cell.
- */
- valueGetter?: GridValueGetter<R, V, F>;
- /**
- * Function that allows to customize how the entered value is stored in the row.
- * It only works with cell/row editing.
- * @returns {R} The row with the updated field.
- */
- valueSetter?: GridValueSetter<R, V, F>;
- /**
- * Function that allows to apply a formatter before rendering its value.
- */
- valueFormatter?: GridValueFormatter<R, V, F>;
- /**
- * Function that takes the user-entered value and converts it to a value used internally.
- * @returns {V} The converted value to use internally.
- */
- valueParser?: GridValueParser<R, V, F>;
/**
* Class name that will be added in cells for that column.
*/
@@ -289,65 +279,131 @@ export interface GridBaseColDef<R extends GridValidRowModel = GridValidRowModel,
* @default 1
*/
colSpan?: number | GridColSpanFn<R, V, F>;
-}
-
-/**
- * Column Definition interface used for columns with the `actions` type.
- * @demos
- * - [Special column properties](/x/react-data-grid/column-definition/#special-properties)
- */
-export interface GridActionsColDef<R extends GridValidRowModel = any, V = any, F = V>
- extends GridBaseColDef<R, V, F> {
/**
* The type of the column.
- * @default 'actions'
- */
- type: 'actions';
- /**
- * Function that returns the actions to be shown.
- * @param {GridRowParams} params The params for each row.
- * @returns {React.ReactElement<GridActionsCellItemProps>[]} An array of [[GridActionsCell]] elements.
+ * @default 'string'
+ * @see See {@link https://mui.com/x/react-data-grid/column-definition/#column-types column types docs} for more details.
*/
- getActions: (params: GridRowParams<R>) => React.ReactElement<GridActionsCellItemProps>[];
+ type?: GridColType;
}
-/**
- * Column Definition interface used for columns with the `singleSelect` type.
- * @demos
- * - [Special column properties](/x/react-data-grid/column-definition/#special-properties)
- */
-export interface GridSingleSelectColDef<R extends GridValidRowModel = any, V = any, F = V>
- extends GridBaseColDef<R, V, F> {
+export interface GridValueMethods<
+ T extends GridColType,
+ R extends GridValidRowModel = GridValidRowModel,
+ V = any,
+ F = V,
+> {
/**
- * The type of the column.
- * @default 'singleSelect'
+ * Function that allows to get a specific data instead of field to render in the cell.
*/
- type: 'singleSelect';
+ valueGetter?: GridValueGetter<R, V, F, ValueBasedType<T>>;
/**
- * To be used in combination with `type: 'singleSelect'`. This is an array (or a function returning an array) of the possible cell values and labels.
+ * Function that allows to customize how the entered value is stored in the row.
+ * It only works with cell/row editing.
+ * @returns {R} The row with the updated field.
*/
- valueOptions?: Array<ValueOptions> | ((params: GridValueOptionsParams<R>) => Array<ValueOptions>);
+ valueSetter?: GridValueSetter<R, V, F>;
/**
- * Used to determine the label displayed for a given value option.
- * @param {ValueOptions} value The current value option.
- * @returns {string} The text to be displayed.
+ * Function that allows to apply a formatter before rendering its value.
*/
- getOptionLabel?: (value: ValueOptions) => string;
+ valueFormatter?: GridValueFormatter<R, V, F, ValueBasedType<T>>;
/**
- * Used to determine the value used for a value option.
- * @param {ValueOptions} value The current value option.
- * @returns {string} The value to be used.
+ * Function that takes the user-entered value and converts it to a value used internally.
+ * @returns {V} The converted value to use internally.
*/
- getOptionValue?: (value: ValueOptions) => any;
+ valueParser?: GridValueParser<R, V, F>;
}
+/**
+ * Column Definition interface used for columns with the `actions` type.
+ * @demos
+ * - [Special column properties](/x/react-data-grid/column-definition/#special-properties)
+ */
+export type GridActionsColDef<R extends GridValidRowModel = any, V = any, F = V> = GridBaseColDef<
+ R,
+ V,
+ F
+> &
+ GridValueMethods<'actions', R, V, F> & {
+ /**
+ * The type of the column.
+ * @default 'actions'
+ */
+ type: 'actions';
+ /**
+ * Function that returns the actions to be shown.
+ * @param {GridRowParams} params The params for each row.
+ * @returns {React.ReactElement<GridActionsCellItemProps>[]} An array of [[GridActionsCell]] elements.
+ */
+ getActions: (params: GridRowParams<R>) => React.ReactElement<GridActionsCellItemProps>[];
+ };
+
+/**
+ * Column Definition interface used for columns with the `singleSelect` type.
+ * @demos
+ * - [Special column properties](/x/react-data-grid/column-definition/#special-properties)
+ */
+export type GridSingleSelectColDef<
+ R extends GridValidRowModel = any,
+ V = any,
+ F = V,
+> = GridBaseColDef<R, V, F> &
+ GridValueMethods<'singleSelect', R, V, F> & {
+ /**
+ * The type of the column.
+ * @default 'singleSelect'
+ */
+ type: 'singleSelect';
+ /**
+ * To be used in combination with `type: 'singleSelect'`. This is an array (or a function returning an array) of the possible cell values and labels.
+ */
+ valueOptions?:
+ | Array<ValueOptions>
+ | ((params: GridValueOptionsParams<R>) => Array<ValueOptions>);
+ /**
+ * Used to determine the label displayed for a given value option.
+ * @param {ValueOptions} value The current value option.
+ * @returns {string} The text to be displayed.
+ */
+ getOptionLabel?: (value: ValueOptions) => string;
+ /**
+ * Used to determine the value used for a value option.
+ * @param {ValueOptions} value The current value option.
+ * @returns {string} The value to be used.
+ */
+ getOptionValue?: (value: ValueOptions) => any;
+ };
+
+export type GridTypedValueColDef<
+ R extends GridValidRowModel = any,
+ V = any,
+ F = V,
+> = GridBaseColDef<R, V, F> &
+ (
+ | ({
+ type?: 'string';
+ } & GridValueMethods<'string', R, V, F>)
+ | ({
+ type: 'number';
+ } & GridValueMethods<'number', R, V, F>)
+ | ({
+ type: 'date' | 'dateTime';
+ } & GridValueMethods<'date', R, V, F>)
+ | ({
+ type: 'boolean';
+ } & GridValueMethods<'boolean', R, V, F>)
+ | ({
+ type: 'custom';
+ } & GridValueMethods<'custom', R, V, F>)
+ );
+
/**
* Column Definition interface.
* @demos
* - [Column definition](/x/react-data-grid/column-definition/)
*/
export type GridColDef<R extends GridValidRowModel = any, V = any, F = V> =
- | GridBaseColDef<R, V, F>
+ | GridTypedValueColDef<R, V, F>
| GridActionsColDef<R, V, F>
| GridSingleSelectColDef<R, V, F>; I guess this could be improved a bit still, but it works as long as you type the columns as we do normally in our docs as well: WDYT? |
@michelengelen This is based on the assumption that the {
field: 'dateString',
type: 'date',
// convert string to Date
valueGetter: (value) => new Date(value),
} Furthermore, there's no way to override the assumed type if necessary. I would rather look into the TypeScript builder approach where we can use generic type variables to infer the actual type based on the field |
So So something like this:
But this feels somewhat wrong.
Overridability can be restored. No problem.
This is an interesting approach. I have used type inference in the past and it led to some nasty errors at that time. Maybe this got better during the latest typescript releases. I will test this in the codebase! Thanks for the suggestions! |
The problem in depth
I have an issue while migrating from 6.x to 7.x.
In a lot of places I have the
valueFormatter
method configured as such:this needs to be changed to
However in 7.x the generic type of
value
here defaults tonever
and Typescript will not complain when attempting to destructure this:https://www.typescriptlang.org/play/?noUncheckedIndexedAccess=true&noUnusedLocals=true&noUnusedParameters=true&exactOptionalPropertyTypes=true&suppressImplicitAnyIndexErrors=true&noPropertyAccessFromIndexSignature=true&noImplicitOverride=true&noFallthroughCasesInSwitch=true#code/C4TwDgpgBAQgTgewNYQHYDECuqDGwCWCqUAvFABQCGcA5gFxSoQBuEcAlKQHxTML4ATAFBCcRAM7AoAM1QN4yNFlwEipCgG9gESQF9OJHhqFRTUManEIANhAB01hDXLbJ7IbqA
I've tried running codemods, but they did nothing.
BTW. I would like to know why
never
was chosen here instead ofunknown
, which would at least make it explode.Your environment
`npx @mui/envinfo`
tsconfig
Search keywords: GridValueFormatter
Order ID: 86856
The text was updated successfully, but these errors were encountered: