MUI dataGridのfiled部分を型チェックする方法

MUI x Ts x Reactで最近開発を進めています

データの出力部分にMUIのDataGridを使っているのですがfiledに型が効かないので拡張して対応しました

mui.com

MUI DataGrid

DataGridは便利で素晴らしいコンポーネントなのですがfiledに型が効きません。

※ MUI data-gridのページから引用

const columns: GridColDef[] = [
  { field: 'id', headerName: 'ID', width: 90 },
  {
    field: 'firstName', <- ここ
    headerName: 'First name',
    width: 150,
    editable: true,
  },
  {
    field: 'lastName', <- ここ
    headerName: 'Last name',
    width: 150,
    editable: true,
  },
  {
    field: 'age', <- ここ
    headerName: 'Age',
    type: 'number',
    width: 110,
    editable: true,
  },
];

内部のコード見た感じfiledがstirng型として定義されています。
なので間違って存在しないfield名を入れても通っちゃうんですね。

Row型の定義

DataGridで使用するrecordに型を付けます。

  type Row = {
    id: number,
    firstName: string,
    lastName: string,
    age: number,
  }

  const info: Array<Row> = [
    {
      id: 0,
      firstName: "xxx",
      lastName: "xxx",
      age: 0,
    },
    {
      id: 1,
      firstName: "xxx",
      lastName: "xxx",
      age: 0,
    }
  ]

GridColDefの拡張

以下のようなinterfaceでMUI DataGridのGridColDefを拡張して対応することにしました。

 interface ColDef<T extends string> extends GridColDef {
  field: T
}

fieldの型に互換性を持たせるためにstring型を継承させています。
また、項目を追加したい場合、以下のように | で繋ぐと表現できます。

 interface ColDef<T extends string> extends GridColDef {
  field: T | '操作'
}

使い方

今回、interfaceやtypeを同一ファイルに入れていますが分離させてください
(例えばColDefに関してはDataGridのwrapperコンポーネントでexportするなど)

 interface ColDef<T extends string> extends GridColDef {
  field: T
}

# GridColDefをColDefに修正
const columns: ColDef<keyof Row>[] = [
  { field: 'id', headerName: 'ID', width: 90 },
  {
    field: 'firstName',
    headerName: 'First name',
    width: 150,
    editable: true,
  },
  {
    field: 'lastName',
    headerName: 'Last name',
    width: 150,
    editable: true,
  },
  {
    field: 'age',
    headerName: 'Age',
    type: 'number',
    width: 110,
    editable: true,
  },
];

これで以下のようにfirst_nameでタイポしててもエラーが出てくれます。

const columns: ColDef<keyof Row>[] = [
  { field: 'id', headerName: 'ID', width: 90 },
  {
    field: 'first_name',
    headerName: 'First name',
    width: 150,
    editable: true,
  },
  {
    field: 'lastName',
    headerName: 'Last name',
    width: 150,
    editable: true,
  },
  {
    field: 'age',
    headerName: 'Age',
    type: 'number',
    width: 110,
    editable: true,
  },
];
エラー文:   
[ 型 '"first_name"' を型 'keyof Row' に割り当てることはできません。'"firstName"' でよろしいですか? ]

Rowに存在しないフィールド名を付けたい場合はこんな感じです。
| で繋ぐ。

const columns: ColDef<keyof Row | "fullName">[] = [
  { field: 'id', headerName: 'ID', width: 90 },
  {
    field: 'firstName',
    headerName: 'First name',
    width: 150,
    editable: true,
  },
  {
    field: 'lastName',
    headerName: 'Last name',
    width: 150,
    editable: true,
  },
  {
    field: 'age',
    headerName: 'Age',
    type: 'number',
    width: 110,
    editable: true,
  },
  {
    field: 'fullName',
    headerName: 'Full name',
    description: 'This column has a value getter and is not sortable.',
    sortable: false,
    width: 160,
    valueGetter: (params: GridValueGetterParams) =>
      `${params.row.firstName || ''} ${params.row.lastName || ''}`,
  },
];

filed名間違えてタイポすることって結構あると思います。
それを事前に型で防ぐための対策でした。