eslint-plugin-total-functions
eslint-plugin-total-functions copied to clipboard
[no-unsafe-readonly-mutable-assignment] False negative with Object.assign
const x: { readonly a: number } = { a: 1 };
Object.assign(x, { a: 3 });
This should warn, I guess, but it doesn't. Am I missing something? Shouldn't this rule handle that case?
Thanks @boris-petrov, you're right. I'd be happy to accept a PR for this.
I can recommend https://github.com/eslint-functional/eslint-plugin-functional/blob/main/docs/rules/immutable-data.md and even https://github.com/eslint-functional/eslint-plugin-functional/blob/main/docs/rules/no-expression-statements.md
Either of those rules will flag Object.assign(x, { a: 3 });
as problematic.
It's difficult for this rule to catch this issue due to the way Object.assign
is typed:
assign<T extends {}, U>(target: T, source: U): T & U
The parameter type declared by assign
is T extends {}
(in your case this is { readonly a: number }
) and the argument type is the same.
So this rule is comparing assignment from T
to T
, which it considers valid.
This is distinct from the situation where you have an assignment like
type ReadonlyA = { readonly a: string };
const readonlyA: ReadonlyA = { a: "" };
where the types are different - { readonly a: string }
and { a: string }
.
For this reason I'm going to close this one and recommend you use the eslint-plugin-functional rules I mention above.
The readme here does recommend using it already: https://github.com/danielnixon/eslint-plugin-total-functions#setup