The material-ui components declare their types as mutable when in fact they are treated as immutable by material-ui.
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.
Values of a readonly type should be able to be given to material-ui components.
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:
I'm trying to have a fully immutable and function code base using the linting rules defined in eslint-plugin-functional.
| Tech | Version |
| ----------- | ------- |
| Material-UI core | v4.9.7 |
| Material-UI lab | v4.0.0-alpha.46 |
| React | v16.13.0 |
| TypeScript | v3.8.3 |
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: