{"record":{"id":"dcdb29ce78f6cba4","repo":"oxc-project/oxc","slug":"do-not-assign-to-imported-bindings","errorCode":null,"errorMessage":"Do not assign to imported bindings","messagePattern":"Do not assign to imported bindings","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/oxc_linter/src/rules/eslint/no_import_assign.rs","lineNumber":14,"sourceCode":"use oxc_ast::{\n    AstKind,\n    ast::{AssignmentTarget, AssignmentTargetMaybeDefault, Expression, ImportDeclarationSpecifier},\n};\nuse oxc_diagnostics::OxcDiagnostic;\nuse oxc_macros::declare_oxc_lint;\nuse oxc_semantic::{AstNode, NodeId, Reference};\nuse oxc_span::{GetSpan, Span};\nuse oxc_syntax::operator::UnaryOperator;\n\nuse crate::{context::LintContext, rule::Rule};\n\nfn no_import_assign_diagnostic(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Do not assign to imported bindings\")\n        .with_help(\"Imported bindings are readonly\")\n        .with_label(span)\n}\n\n#[derive(Debug, Default, Clone)]\npub struct NoImportAssign;\n\ndeclare_oxc_lint!(\n    /// ### What it does\n    ///\n    /// Disallow assigning to imported bindings.\n    ///\n    /// ### Why is this bad?\n    ///\n    /// The updates of imported bindings by ES Modules cause runtime errors.\n    ///\n    /// The TypeScript compiler generally enforces this check already. Although\n    /// it should be noted that there are some cases TypeScript does not catch, such","sourceCodeStart":1,"sourceCodeEnd":32,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/eslint/no_import_assign.rs#L1-L32","documentation":"Diagnostic from oxlint's no-import-assign rule (ESLint port, eslint:recommended). Imported bindings are read-only live bindings in ES modules; writing to them fails at runtime (TypeError in browsers, SyntaxError in Node for plain assignment). The rule statically flags every write to an import binding: plain and compound assignment, increment/decrement, destructuring assignment targets, for-of targets, and deletes or writes on namespace members.","triggerScenarios":"import { a } from 'm'; a = 1;; import def from 'm'; def += 1; or ++def;; [a] = pairs; where a is imported; for (a of list);; import * as ns from 'm'; ns.foo = 1; or delete ns.foo;","commonSituations":"Trying to mock or override an imported value in tests; attempts to reconfigure imported constants; cyclic-module workarounds that assign into imports to break loops.","solutions":["Assign to a fresh local copy: let local = a; local = 1;.","For mutable shared state, export a setter function or a mutable object from the module.","In tests, use the loader's mocking API (vi.mock / jest.mock) instead of assignment.","Remove the write entirely; imported bindings are a read-only contract."],"exampleFix":"// before\nimport { count } from './store.js';\ncount = 10;\n\n// after\nimport { setCount } from './store.js';\nsetCount(10);","handlingStrategy":"validation","validationCode":"npx oxlint -A all -D no-import-assign src/","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat import bindings as const.","Export setter functions for mutable module state.","Use vi.mock/jest.mock for test doubles; never assign to imports."],"tags":["eslint","oxlint","lint","modules","imports","assignment"],"backgroundTag":"import-binding-reassignment","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}