Material-ui: TypeInfo: Should use readonly types over mutable types.

Created on 25 Mar 2020  路  5Comments  路  Source: mui-org/material-ui

The material-ui components declare their types as mutable when in fact they are treated as immutable by material-ui.

  • [x] The issue is present in the latest release.
  • [x] I have searched the issues of this repository and believe that this is not a duplicate.

Current Behavior 馃槸

Values of a readonly type cannot be given to material-ui components.

I've only checked this with the Autocomplete component but I assume there are probably other components affected by this same issue.

Expected Behavior 馃

Values of a readonly type should be able to be given to material-ui components.

Steps to Reproduce 馃暪

Issue demonstrated here codesandbox.io/s/funny-sky-mw1st in the src/App.tsx file.
The prop options cannot be assigned a readonly type.

Steps:

  1. Create a variable of a Readonly type.
  2. Supply that variable to a material-ui component that is expecting a mutable type.

Context 馃敠

I'm trying to have a fully immutable and function code base using the linting rules defined in eslint-plugin-functional.

Your Environment 馃寧

| Tech | Version |
| ----------- | ------- |
| Material-UI core | v4.9.7 |
| Material-UI lab | v4.0.0-alpha.46 |
| React | v16.13.0 |
| TypeScript | v3.8.3 |

typescript waiting for 馃憤

All 5 comments

Yeah these are all technically readonly. It's just so much churn to mark every prop as readonly which probably causes breakage somewhere because people pass their *Props around and mutate them in place.

We can't support this use case. If you're interested in it please upvote the issue.

@eps1lon I don't think this would cause breakages as mutable values can be given to readonly types (as essentially MutableType<T> extends ImmutableType<T> - e.g. Array<T> is Readonly<T> & MutableArrayStuff<T>).

A more clear example:

// This function can be call passing in either a mutable or immutable array.
function max(numbers: ReadonlyArray<number>): number {
  return numbers.reduce(
    (currentMax, number) => (number > currentMax ? number : currentMax),
    Number.NEGATIVE_INFINITY
  );
}

const mutableArray = [1, 2, 3];
const immutableArray = [1, 2, 3] as const;

console.log(max(mutableArray));
console.log(max(immutableArray));

This would throw now, no?

const values: AutoCompleteProps['values'] = []
values.push(1)

Ah yes, that would.

This could be worked around with TypeScript's Mutable type which is proposed here: https://github.com/microsoft/TypeScript/issues/24509

e.g.

type Mutable<T> = {
  -readonly [P in keyof T]: T[P];
};

const values: Mutable<AutoCompleteProps['values']> = []
values.push(1)

But obviously that would still be a breaking change.

For now I'll just use // @ts-ignore with regard to this issue (or I could use prop={[...prop]}).

Edit: Actually, I'll probably just cast to a mutable type.

I get the desire to make this more strict and in the end this might as well not break anything. It's just that I want to avoid different typing approaches across the code base which means we would update types for components that are considered stable. Looking at how much value this provides even a single issue report isn't worth the trouble for us.

But who knows. Maybe this gets traction. Thanks for the quality issue anyway. Always appreciated :+1:

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ghost picture ghost  路  3Comments

TimoRuetten picture TimoRuetten  路  3Comments

ghost picture ghost  路  3Comments

reflog picture reflog  路  3Comments

anthony-dandrea picture anthony-dandrea  路  3Comments