import =
Binds a CommonJS require or an existing namespace to a local name that works in both type and value positions.
import ident = require("mod");
import ident = A.B.C;
export import ident = require("mod");- Added in TypeScript 1.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$ident | identifier | The local name bound to the module's export assignment. Unlike `const x = require(...)`, this binding carries both the value and any types the module exports. |
$require("mod") | module specifier call | The CommonJS require form. Emits `const ident = require("mod")` under a CommonJS target and is preserved as written under `--module preserve`. |
$A.B.Coptional | entity name | The alias form: binds a shorter local name to an existing namespace, class or enum. No module resolution happens and nothing is imported. |
$export (modifier)optional | keyword | Re-exports the alias from the current module or namespace. |
Errors
Raises "import ... = require(...) is not allowed when '--module' is set to 'esnext'" (or any ES module target/format), and "An import declaration can only be used at the top level of a namespace or module" when nested elsewhere.
Changelog
- PHP 2.7`esModuleInterop` added, making `import x from "cjs-mod"` work against `export =` modules and removing most reasons to write `import =`.
- PHP 4.7Under `--module node16`/`nodenext`, `import =` is rejected in ES module files (`.mts`, or `.ts` under `"type": "module"`), because it has no ESM meaning.
- PHP 5.0`verbatimModuleSyntax` requires `import =` in CommonJS-format files: ES `import` syntax is no longer rewritten to `require`.
import x = require("mod") is TypeScript's pre-ES2015 import. It exists because const x = require("mod") creates a value binding only, so a module that publishes a type through export = cannot be consumed that way — const Options = require("./a") gives you a value named Options, not a type you can annotate with. The import = form binds both meanings at once.
When to reach for it
- A dependency uses
export =and you haveesModuleInteropoff. This is the only way to import it cleanly. - A CommonJS-format file under
verbatimModuleSyntax. That flag stops rewriting ESimportintorequire, so CJS files must sayimport =explicitly. - Aliasing a nested namespace, e.g.
import Shapes = Geometry.TwoD.Shapes, which involves no module at all.
What trips people up
Most projects today set esModuleInterop: true, which synthesises a default export for CommonJS modules and makes import x from "mod" work. Once that is on, import = is rarely needed — and it becomes an outright error the moment the file is treated as ESM, which is what happens when you add "type": "module" to package.json under --module nodenext.
Example
// node_modules/legacy-logger/index.d.ts
declare function log(msg: string): void;
declare namespace log {
interface Options { level: "debug" | "info" }
}
export = log;
// app.ts (CommonJS format)
import log = require("legacy-logger");
const opts: log.Options = { level: "debug" }; // type side
log(`level=${opts.level}`); // value side
console.log(opts);
// -> { level: "debug" }
// Emits: const log = require("legacy-logger");When to use it
- Consume a package that declares export = while esModuleInterop is turned off
- Write a CommonJS .cts file under verbatimModuleSyntax where import/export is no longer rewritten
- Alias a deeply nested namespace to a short local name inside a declaration file
- Import a legacy typings package whose root export is a callable function with attached types
Frequently asked questions
When should I use import = require() instead of a normal import?
Use it when the module publishes its API through `export =` and `esModuleInterop` is off, or when you are in a CommonJS-format file under `verbatimModuleSyntax`, which no longer rewrites ES import syntax into require. In every other modern setup, turn on `esModuleInterop` and write a normal default import.
Why does import = require() error under module esnext or nodenext?
Because the form has no ES module equivalent — it compiles to a synchronous `require` call, which does not exist in ESM. TypeScript rejects it in any file it treats as an ES module, including `.mts` files and `.ts` files in a package with `"type": "module"`.
What is the difference between import x = require("m") and const x = require("m")?
`import x = require("m")` binds both the value and the types the module exports, so `x.SomeType` works as an annotation; `const x = require("m")` creates a value binding only, typed `any` unless you annotate it, and gives you no access to exported types.
More examples
The same import with esModuleInterop on
With esModuleInterop the compiler synthesises a default export for the `export =` module and emits an interop helper, so the standard `import ... from` form binds the callable. This is the version you should write in new code; the `import =` form is what you fall back to when the flag is off or the file is explicitly CommonJS under verbatimModuleSyntax.
// tsconfig.json: { "compilerOptions": { "esModuleInterop": true, "module": "commonjs" } }
// node_modules/legacy-logger/index.d.ts
declare function log(msg: string): void;
declare namespace log {
interface Options { level: "debug" | "info" }
}
export = log;
// app.ts — ordinary ESM syntax now works
import log from "legacy-logger";
import type { Options } from "legacy-logger";
const opts: Options = { level: "info" };
log(`level=${opts.level}`);
console.log(opts.level);
// -> "info"Namespace aliasing — no module involved
Here `import =` performs no module resolution at all — it is a local alias for a namespace that already exists in scope, and `Flat` works as both a type namespace (`Flat.Point`) and a value (`Flat.distance`). A `const Flat = Geometry.TwoD` would give you the function but leave `Flat.Point` unresolvable as a type.
namespace Geometry {
export namespace TwoD {
export interface Point { x: number; y: number }
export function distance(a: Point, b: Point): number {
return Math.hypot(a.x - b.x, a.y - b.y);
}
}
}
// Alias form: binds an existing entity, emits `var Flat = Geometry.TwoD;`
import Flat = Geometry.TwoD;
const a: Flat.Point = { x: 0, y: 0 };
const b: Flat.Point = { x: 3, y: 4 };
console.log(Flat.distance(a, b));
// -> 5
Discussion