シェルパ・アンド・カンパニー株式会社 エンジニアブログ

シェルパ・アンド・カンパニー株式会社のエンジニアが技術情報を発信します

MUI DataGridPremiumでcolumnとfilterModelのfield型を連携させて型安全にする

シェルパ・アンド・カンパニー株式会社でプロダクト開発を担当しているペトロフです。開発中に抱えていた課題を踏まえ、Tipsを公開します。

補足

  • 使用するTypeScriptのVersionは5.8.3
  • 使用する@mui/x-data-grid-premiumのVersionは^6.18.1
  • 使用するIDEVScode

やりたいこと

以下のソースではcolumnsfilterModelではfieldをstring型で自由に設定できます。しかし、columnsfilterModelfield値が合わなければ、フィルタ機能は正常に動作しません。そもそもstring型で自由に文字列を設定できることに違和感がありました。

値が統一されず、無秩序に設定ができてしまうためです。例えば、columns側のfield値だけをfirstNameからfullNameに変更してもエラーにならないため、気付かないうちにデグレード(機能劣化)が発生する可能性があります。今回はcolumnsfilterModelfieldをgeneric型で指定し、fieldで特定以外の値を入力されたら型エラーになるようにしたいです。

import { GridColDef, GridFilterModel, DataGridPremium } from "@mui/x-data-grid-premium";

type RowType = {
  id: number;
  lastName: string;
  firstName: string;
};

export const DataGridTestComp = () => {
  const rows = [
    { id: 1, lastName: "Snow", firstName: "Jon" },
    { id: 2, lastName: "Lannister", firstName: "Cersei" },
    { id: 3, lastName: "Lannister", firstName: "Jaime" },
    { id: 4, lastName: "Stark", firstName: "Arya" },
    { id: 5, lastName: "Targaryen", firstName: "Daenerys" },
  ];

  const columns: GridColDef<RowType>[] = [
    { field: "firstName", headerName: "First name", width: 130 },
    { field: "lastName", headerName: "Last name", width: 130 },
  ];

  const filterModel: GridFilterModel = {
    items: [
      {
        field: "firstName",
        operator: "contains",
        value: "J",
      },
    ],
  };
  return <DataGridPremium rows={rows} columns={columns} filterModel={filterModel} />;
};

型定義ファイル

x-data-grid-premium.d.ts等の型定義ファイルを作成します。 以下のようにcolumnの型であるGridColDefと、filterModelの型であるGridFilterModelを拡張し、genericで指定された型をfieldに適用できるようにします。

import {
  GridBaseColDef as MuiGridBaseColDef,
  GridActionsColDef as MuiGridActionsColDef,
  GridSingleSelectColDef as MuiGridSingleSelectColDef,
  GridValidRowModel as MuiGridValidRowModel,
  GridFilterItem as MuiGridFilterItem,
} from "@mui/x-data-grid-premium";

declare module "@mui/x-data-grid-premium" {
  export interface GridBaseColDef<
    R extends MuiGridValidRowModel = MuiGridValidRowModel,
    V = any,
    F = V,
    FieldType extends string = string,
  > extends MuiGridBaseColDef<R, V, F> {
    field: FieldType;
  }

  export type GridColDef<R extends MuiGridValidRowModel = any, FieldType extends string = string, V = any, F = V> =
    | GridBaseColDef<R, V, F, FieldType>
    | MuiGridActionsColDef<R, V, F>
    | MuiGridSingleSelectColDef<R, V, F>;

  export type GridFilterModel<FieldType extends string = string> = {
    items: Array<
      Omit<MuiGridFilterItem, "field"> & {
        field: FieldType;
      }
    >;
  };
}

拡張した型を実際に使ってみる

これで完成です。columnfilterModelfieldにid,lastName,firstNameの文字以外を入力すると、型エラーが起きるはずです。また、field値を入力する際にVSCodeのIntelliSenseで補完もできます。

import { GridColDef, GridFilterModel, DataGridPremium } from "@mui/x-data-grid-premium";

type RowType = {
  id: number;
  lastName: string;
  firstName: string;
};

type FieldKeys = keyof RowType;

export const DataGridTestComp = () => {
  const rows: RowType[] = [
    { id: 1, lastName: "Snow", firstName: "Jon" },
    { id: 2, lastName: "Lannister", firstName: "Cersei" },
    { id: 3, lastName: "Lannister", firstName: "Jaime" },
    { id: 4, lastName: "Stark", firstName: "Arya" },
    { id: 5, lastName: "Targaryen", firstName: "Daenerys" },
  ];

  const columns: GridColDef<RowType, FieldKeys>[] = [
    { field: "firstNames", headerName: "First name", width: 130 },
    { field: "lastName", headerName: "Last name", width: 130 },
  ];

  const filterModel: GridFilterModel<FieldKeys> = {
    items: [
      {
        field: "firstNames",
        operator: "contains",
        value: "J",
      },
    ],
  };
  return <DataGridPremium rows={rows} columns={columns} filterModel={filterModel} />;
};

シェルパ・アンド・カンパニーでは一緒に働く仲間を募集しています。

https://herp.careers/v1/cierpa0905