Typescript: Cannot assign immutable state from payload to immutable writable draft
gracicot opened this issue Β· comments
π Bug Report
Immer exposes a Immutable
helper type that deeply mark a type as readonly:
type A = Immutable<{ a: number }>;
const a: A = {
a: 4
};
a.a = 5; // error, a.a is readonly
Immer also conveniently make it so that a WritableDraft<...>
will let you assign to subobjects since immer will not mutate the original state, which is correct:
const a2 = produce(a, (draft) => {
// draft is WritableDraft<Immutable<...>>
draft.a = 5;
});
However, writable draft don't let an immutable value be assigned to another immutable value:
type B = Immutable<{ arr: number[] }>;
const b1: B = {
arr: [1, 2, 3]
};
const b2: B = {
arr: [4, 5, 6]
};
produce(b1, draft => {
draft.arr = b2.arr;
});
This is technically correct as arr
will be assigned to another mutable value
This issue arises a lot when you have an immutable state in redux, use a selector and send back a state in an action payload. When action payloads are immutable, this issue will trigger.
Link to repro
A bug report without a reproduction is not a bug report. Failing to follow this templately is likely to result in an immediate close & lock of the issue.
To Reproduce
Steps to reproduce the behavior:
type B = Immutable<{ arr: number[] }>;
const b1: B = {
arr: [1, 2, 3]
};
const b2: B = {
arr: [4, 5, 6]
};
produce(b1, draft => {
draft.arr = b2.arr;
});
Observed behavior
Typescript refuses the code
Expected behavior
Typescript should accept the code
Environment
We only accept bug reports against the latest Immer version.
- Immer version: 10.1.1
- I filed this report against the latest version of Immer
- Occurs with
setUseProxies(true)
- Occurs with
setUseProxies(false)
(ES5 only)
It seems castDraft
works. It still would be nice to not need that so I'll keep the issue open. I'm the case it is completely unfixable, then maintainers can close this issue.