oxc-project/oxc · error · OxcDiagnostic

TS1202

TS1202

Error message

Import assignment cannot be used when targeting ECMAScript modules.

What it means

This is Oxc's port of TypeScript error TS1202: `import x = require("...")` (TSImportEqualsDeclaration with an ExternalModuleReference) is a CommonJS-style import assignment and cannot be emitted when the output module format is ECMAScript modules. The TypeScript module transform lowers it to `const x = require("...")` and reports the diagnostic when `self.module.is_esm()` at crates/oxc_transformer/src/typescript/module.rs:157-159. Note `Module::is_esm()` (options/module.rs:28) is true only for `Module::Esm`; the default `Module::Preserve` does not trigger it.

Source

Thrown at crates/oxc_transformer/src/typescript/diagnostics.rs:6

use oxc_diagnostics::OxcDiagnostic;
use oxc_span::Span;

#[cold]
pub fn import_equals_cannot_be_used_in_esm(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Import assignment cannot be used when targeting ECMAScript modules.")
        .with_help(
            "Consider using 'import * as ns from \"mod\"',
         'import {a} from \"mod\"', 'import d from \"mod\"', or another module format instead.",
        )
        .with_label(span)
        .with_error_code("TS", "1202")
}

#[cold]
pub fn export_assignment_cannot_bed_used_in_esm(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Export assignment cannot be used when targeting ECMAScript modules.")
        .with_help("Consider using 'export default' or another module format instead.")
        .with_label(span)
        .with_error_code("TS", "1203")
}

#[cold]
pub fn ambient_module_nested(span: Span) -> OxcDiagnostic {

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Replace with ESM syntax: `import * as ns from "mod"`, `import { a } from "mod"`, or default-import `import d from "mod"` (the help text in diagnostics.rs lists exactly these)
  2. If the import exists only to defer/lazy-load, use dynamic import: `const mod = await import("mod")` or `import("mod").then(...)`
  3. If the file must stay CommonJS-style, set the transform's module option to `commonjs` so `module.is_esm()` is false (note: `Preserve`, the default, also does not error)
  4. For pure type aliases to modules, mark it type-only (`import type x = require('m')`) or ensure all references are types so it is removed instead of lowered

Example fix

// before
import utils = require('./utils');
export = doThing(utils);

// after
import * as utils from './utils';
export default doThing(utils);
Defensive patterns

Strategy: validation

Validate before calling

// Before running the ESM-output transform, detect import-equals in sources
function hasImportEquals(src: string): boolean {
  return /^\s*(export\s+)?import\s+\w+\s*=\s*require\s*\(/m.test(src);
}
// Grounded decision: only warn when output module is Esm
const moduleIsEsm = transformOptions.module === 'esm';
if (moduleIsEsm && hasImportEquals(src)) failBuild('rewrite import x = require(...)');

Type guard

// Static guard for a TS codebase: ban the syntax via config instead of runtime
tsconfig: { "module": "esnext", "verbatimModuleSyntax": true } // makes tsc flag import = for ESM

Try / catch

// oxc collects diagnostics rather than throwing; gate your pipeline on the TS code
let result = transformer.build(source);
result.errors.iter().filter(|d| d.code() == Some(("TS", "1202"))).for_each(|d| {
    route_to_esm_migration_todo(d);
});

Prevention

When it happens

Trigger: Configuring oxc-transform with `module: Esm` (or a Babel config mapping to ESM output) and transforming TypeScript containing `import fs = require('node:fs');` where the import has value references (type-only usages are stripped earlier). Both classic `import x = require('m')` forms and re-exported ones (`export import x = require('m')` reaches the same path via enter_declaration) can trip it.

Common situations: Migrating a legacy TS codebase (originally `module: commonjs`, full of `import x = require(...)` for cycles or lazy requires) to ESM output (`module: esnext`/`preserve`+ESM bundler); Node dual-mode packages where CJS-style TS is reused in an ESM build; copying wiring/ORM snippets written for old Electron or Vue 2 toolchains into an ESM-targeted oxc pipeline.

Related errors


AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20). Data as JSON: /api/errors/90f4a9452c2c216c. Report an issue: GitHub.