Assigning a value to an import variable will cause a runtime error and will raise a compilation error in TypeScript.
Named imports
When using named imports, the imported identifier is a live binding exported by another module. Live bindings can be updated or reassigned
by the exporting module, and the imported value would also change. The importing module cannot reassign it.
import { exportedObject } from 'module.js';
exportedObject = 'hello world!'; // Noncompliant: TypeError: Assignment to constant variable.
This rule will not raise an issue when a module mutates the imported object. Be aware that all other modules importing the same
value will observe the mutated value.
import { exportedObject } from 'module.js';
exportedObject.newAttribute = 'hello world!'; // exportedObject now contains newAttribute and can be seen from all other modules importing it
Namespace and dynamic imports
This rule will raise an issue when modifying members of a module namespace
object. A module namespace object is a sealed object that describes all exports from
a module.
This can be done using
import * as module from 'module.js';
module.newObject = module.exportedObject; // Noncompliant: TypeError: Cannot add property readPath, object is not extensible
- the fulfillment value of a dynamic import.
import('module.js').then(module => {
module.newObject = module.exportedObject; // Noncompliant: TypeError: Cannot add property readPath, object is not extensible
})
Default imports
Default imports are live bindings to the default
export. As with the other forms of import
declarations, the importing
module cannot reassign it.
import module from 'module.js';
module = 'hello world!'; // Noncompliant: TypeError: Assignment to constant variable.
However, the object which default
refers to is not a live binding and may still be mutated by importing modules.
import moduleDefault from 'module.js';
moduleDefault.newAttribute = 'hello world!'; // module.default now contains newAttribute and can be seen from all other modules importing it