Repository: material-ui
Issue: [Discussion] Versioning strategy for the typings
Labels: discussion,typescript

### Summary 💡

On https://github.com/mui-org/material-ui-x, we had a discussion this week around the breaking changes on the TypeScript interfaces and how we should handle them.

One of the conclusion of the meeting was that the two repositories should follow the same strategy on this.
So I am creating this issue to discuss it with your team.

The definition of a Breaking Change for JS code is most of the time pretty straightforward.
But when it comes to interfaces (or CSS, or tests), any change can quickly become breaking for some developers doing advanced usage of the exported interfaces.

## Goals

The code here is to define what is considered acceptable in our typing versioning strategy and to clearly explain it on the documentation.

For me it is obvious that the breaking change must remain as rare as possible and that they must clearly by explained in the changelog.

But focusing on doing 0 typing breaking change seems hard to me and I don't think a small typing breaking change should prevent a feature from being released several months before the next major version.

A very bad solution to that problem would be to type less precisely. Because the more you type, the more you export interfaces to help the user, the harder it becomes to avoid doing a typing breaking change.


## Breaking change example

Before https://github.com/mui-org/material-ui-x/pull/3314/files, the `valueGetter` method had the following signature:

```tsx
interface GridValueGetterParams {
  // ... other keys
  getValue: (id: GridRowId, field: string) => GridCellValue;
  rowNode: GridRowTreeNodeConfig;
}

valueGetter: (params: GridValueGetterParams) => any,
```

For some feature, I needed to start calling the `valueGetter` very soon in the DataGrid mount process, too soon to be able to have `getValue` or `rowNode`.

So I changed the `valueGetter` signature to

```tsx
interface GridValueGetterFullParams {
  // ... other keys
  getValue: (id: GridRowId, field: string) => GridCellValue;
  rowNode: GridRowTreeNodeConfig;
}

interface GridValueGetterSimpleParams {
  // ... other keys
}

export type GridValueGetterParams = GridValueGetterFullParams | GridValueGetterSimpleParams

valueGetter: (params: GridValueGetterParams) => any,
```

Note that this new call of `valueGetter` only occured for the new feature. No user would have an actual `valueGetter` call from the new call location without explicitly enabling the new feature. So there is no JS breaking change here.

But the type checking could fail (see https://github.com/mui-org/material-ui-x/issues/3548) if the user used `getValue` for instance;

```tsx
valueGetter: params => params.getValue(id, 'status')
```

The easy fix being:

```tsx
valueGetter: params => (params as GridValueGetterFullParams).getValue(id, 'status')
// or better to really handle the new feature
valueGetter: params => {
  const fullParams = params as GridValueGetterFullParams
  if (!params.getValue) {
    return null
  }

  return params.getValue(id, 'status')
}
```

For that breaking change, we wanted the three following points;

- Do not break the TS compilation of any user
- Have a typing that is correct (ie: that describe the actual parameters that can be passed)
- Use the `valueGetter` for the row grouping

But I can't see how to achieve that.
For me, we either had to:

- Break the TS compilation (what we did)
- Tell TypeScript that `getValue` was defined even when it's a lie
- Postpone the whole feature to v6 even though it's one of the most asked by the community

Note that we did not explain the breaking change in the changelog and that's wrong, we should have spotted it and added a clear migration example.

## Benchmark

Strategies used by other popular repositories: 

- …

## Our options

…