-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a Mutable type (opposite of Readonly) to lib.d.ts #24509
Comments
Readonly modifiers "are a joke" (#13002) so this would still compile: interface I { readonly x: number; readonly y: number; }
type Mutable<T> = {
-readonly[P in keyof T]: T[P]
};
declare const i: I;
const j: Mutable<I> = i; |
@andy-ms I can see why that would be undesired. Ideally you wouldn't be able to assign I don't want to discuss whether or not |
I'd really like to see this as part of typescript, it is quite useful in unit tests. On the other hand I've encountered an issue and I think this type should be
but this does not remove readonly flag and without this you are not able to pass Mutable to a function that accepts Foo if your object has private properties |
I have something similar in my codebase, but that covers
This can probably be generalized to cover other non-string arrays too, I just didn't have the need in my usage. But thought it would be nice to cover these if it gets into lib.d.ts |
I actually had to generalize this, and ended up with the following:
This will make properties of a type mutable, plus also turn properties that are |
|
A type DeepMutable<T> = { -readonly [P in keyof T]: DeepMutable<T[P]> }; |
I wish the typescript designers had gone with immutability by default instead of mutability. If all properties and variable declarations were readonly by default then I wouldn't have to type readonly so often. Mutable properties could have used a keyword like |
I suspect that would severely break the "JavaScript is valid Typescript" design point |
@PreventRage How so? The |
@baetheus I think technically you have a point. Which I would restate as "The various My sense is that apply more rigorous rules and force your JS to be cleaner ( Strangely (perhaps I'm totally contradicting myself?) I find the notion of a way to mark an individual type as immutable (I think just a tidier version of the |
@PreventRage Thanks for getting back to me! I understand that immutability is not for everyone, and I often find myself using mutable structures when doing hot path optimization. While I have no particular issues with the argument that immutableByDefault might not be in the spirit of the language as designed, it nevertheless would be useful for me (and probably a few other programmers that I've worked with over the years). That said, I'm not in earnest expecting that such a feature would be implemented, I mainly meant to put forward a feature that would pair well with the proposed As for using the |
I just came across the following minor use case for this: I'm creating a class with public properties I have marked as The class MyClass {
readonly myVal: string;
set(myVal: string) {
(this as Mutable<this>).myVal = myVal;
}
} In general I think it's a good idea to add this helper type just for parity with |
Sorry for bumping an old issue, but I just wanted to say that I too have had to declare my own declare type Mutable<T extends object> = {
-readonly [K in keyof T]: T[K]
} I also typically declare a declare type Struct<T> = {
[key: string]: T
} A standard |
Adding to this here - |
Maybe this can help, although it requires a call to a function
|
I recently commented on a similar topic... what about introducing a For more context, although we know that objects are mutable by default in JS and TS, in TS they can be qualified as "unknown" too (not just "readonly" or "mutable")... and the default qualifier is "unknown", not "mutable". That's why it's possible to do some unsafe assignments without any complaint from the type checker ( #14150 ). The generic My previous comment: In the linked comment I also refer to an old issue that was closed without further public discussion (the conversation seems to be available only for the development team). |
For anyone reading this and looking for |
I keep running into this issue the more I use
However if you try to assign this to something 'wider' then you get tripped up by its ReadOnly nature.
This intuitively just doesn't feel right (even though I understand why): I don't even necessarily want
|
@simeyla You are correct; the way to handle this is to make a copy of It actually enforces type safety to disallow assigning Suppose someone could do this: const animals = ['dog', 'cat', 'mouse'] as const; // type is readonly ["dog", "cat", "mouse"]
// @ts-expect-error
const farm: string[] = animals; then: farm.push('chicken'); now inspect animals; // type is readonly ["dog", "cat", "mouse"]
console.log(animals);
//> ["dog", "cat", "mouse", "chicken"] The immutable object has been mutated! Your solution is correct. You must make a copy: const farm: string[] = [...animals]; // or `animals.slice()`, etc... |
I need this! Currently both
I found that this can and should be used in the definition of |
My use-case is that I have a class with mutable properties in a react-based app, which can be instantiated with properties stored in state. In react, there are immutable values everywhere (e.g. state), so ideally I would like typescript to give me errors if I try to pass an immutable value to a mutable one. I'm currently pulling out my hair hunting for a rogue immutable value that's getting set to a mutable class property, rendering it immutable, and thus useless... // ideally I'd be able to say something like:
class UtilityClass {
public mutableProperty: Mutable<Record<string, string>>
constructor(prop) {
this.mutableProperty = prop;
}
// ...
}
// and then this would happen
const Component = () => {
const [immutableState, setImmutableState] = useState({a: 1});
// Type Error: Can't set 'UtilityClass' mutable property 'mutableProperty' to immutable property 'immutableState'
const classInstance = new UtilityClass(immutableState);
classInstance.mutableProperty.a = 2; // this doesn't work b/c we made it immutable, thankfully TS warned us
// ...
} |
@castarco However, that's kind of tangential to the present issue. I think, if @julian-kingman-lark I think your issue is unrelated to React itself, so I'm rewriting your sample here to make it self-contained: class UtilityClass {
constructor (public mutableProperty: Record<string, string>) {}
}
export const Component = () => {
const immutableState = {a: `1`} as const
const classInstance = new UtilityClass(immutableState) // Type Error with #58296
classInstance.mutableProperty.a = `2` // will never error
} The call to The assignment Your original @simon-robertson |
Search Terms
mutable, mutable type
Suggestion
lib.d.ts contains a
Readonly
type, but not aMutable
type. This type would be the opposite ofReadonly
, defined as:Use Cases
This is useful as a lightweight builder for a type with readonly properties (especially useful when some of the properties are optional and conditional logic is needed before assignment).
Examples
Checklist
My suggestion meets these guidelines:
The text was updated successfully, but these errors were encountered: