typescript/no-unsafe-object-assign
Disallow Object.assign sources that may overwrite readonly target keys.
Targeted pattern scope
⚠️ This rule requires type information to run. Configure type-aware linting (parserOptions.project or projectService) before enabling it.
This rule targets calls matching Object.assign(...), resolves the target and
source types, and compares each source's known property and index-signature
keys with readonly target properties and index signatures.
What this rule reports
This rule reports an Object.assign call only when at least one source may
write a readonly key on the target. Merely having an unrelated readonly target
property is not an error.
Why this rule exists
It prevents Object.assign from bypassing readonly contracts without blocking
safe writes to unrelated mutable properties.
❌ Incorrect
type Target = {
readonly id: string;
count: number;
};
declare const target: Target;
Object.assign(target, { id: "changed" });
✅ Correct
type Target = {
readonly id: string;
count: number;
};
declare const target: Target;
Object.assign(target);
Object.assign(target, {});
Object.assign(target, { count: 2 });
Behavior and migration notes
This rule reports only and does not provide an autofix.
- Multiple sources are checked and the call is reported at most once.
- Union branches, intersections, optional properties, constrained generics, and string, number, or symbol index signatures are analyzed without assuming every target key is written.
- An
anysource is treated conservatively because it may provide any key. unknown,never,null,undefined, and empty sources have no statically known write keys.
Prefer an immutable copy when a source intentionally replaces a readonly key.
Options
This rule has no options.
Additional examples
type Target = {
readonly id: string;
count: number;
};
declare const target: Target;
Object.assign(target, { count: 1 });
// ✅ valid: count is writable
Object.assign(target, { id: "changed" });
// ❌ reported
ESLint flat config example
import etcMisc from "eslint-plugin-etc-misc";
export default [
{
plugins: { "etc-misc": etcMisc },
rules: {
"etc-misc/typescript/no-unsafe-object-assign": "error",
},
},
];
When not to use it
Disable this rule if readonly object mutation via Object.assign is intentionally allowed.
Package documentation
Rule catalog ID: R128
Further reading
Adoption resources
- Start at warning level in CI, then move to error after cleanup.
- Use focused codemods/autofix batches per package or directory.