Skip to main content

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 any source 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.