{"record":{"id":"3294938ce26ef51c","repo":"swc-project/swc","slug":"illegal-conversion-cannot-convert-to-moduled","errorCode":null,"errorMessage":"illegal conversion: Cannot convert {:?} to ModuleDeclaration","messagePattern":"illegal conversion: Cannot convert (.+?) to ModuleDeclaration","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/swc_estree_compat/src/babelify/module_decl.rs","lineNumber":65,"sourceCode":"                ModuleDeclOutput::TsExportAssignment(a.babelify(ctx))\n            }\n            ModuleDecl::TsNamespaceExport(e) => {\n                ModuleDeclOutput::TsNamespaceExport(e.babelify(ctx))\n            }\n            #[cfg(swc_ast_unknown)]\n            _ => panic!(\"unable to access unknown nodes\"),\n        }\n    }\n}\n\nimpl From<ModuleDeclOutput> for ModuleDeclaration {\n    fn from(module: ModuleDeclOutput) -> Self {\n        match module {\n            ModuleDeclOutput::Import(i) => ModuleDeclaration::Import(i),\n            ModuleDeclOutput::ExportDefault(e) => ModuleDeclaration::ExportDefault(e),\n            ModuleDeclOutput::ExportNamed(n) => ModuleDeclaration::ExportNamed(n),\n            ModuleDeclOutput::ExportAll(a) => ModuleDeclaration::ExportAll(a),\n            _ => panic!(\n                \"illegal conversion: Cannot convert {:?} to ModuleDeclaration\",\n                &module\n            ),\n        }\n    }\n}\n\nimpl Babelify for ExportDefaultExpr {\n    type Output = ExportDefaultDeclaration;\n\n    fn babelify(self, ctx: &Context) -> Self::Output {\n        ExportDefaultDeclaration {\n            base: ctx.base(self.span),\n            declaration: ExportDefaultDeclType::Expr(\n                Box::alloc().init(self.expr.babelify(ctx).into()),\n            ),\n        }\n    }","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_estree_compat/src/babelify/module_decl.rs#L47-L83","documentation":"After babelifying a ModuleDecl, the result is a ModuleDeclOutput enum with seven variants, but From<ModuleDeclOutput> for ModuleDeclaration only converts the four plain-ESM ones (Import, ExportDefault, ExportNamed, ExportAll). The three TypeScript-specific variants — TsImportEquals (`import x = require(...)`), TsExportAssignment (`export = ...`), and TsNamespaceExport (`export namespace ...`) — have no plain Babel ModuleDeclaration form, so converting them panics with 'illegal conversion'. This fires in Module::babelify where each module-level item is turned into a Babel node via `.into()`.","triggerScenarios":"Babelifying a Program::Module parsed from TypeScript that still contains `import lib = require('lib')`, `export = value`, or `export namespace NS { ... }` at module top level — e.g. parsing a .ts file as a module and calling babelify without stripping types first.","commonSituations":"Tooling that parses TS with swc and requests the Babel AST flavor (acorn/babel output, AST viewers, codemod pipelines) without running swc's TypeScript stripper; CommonJS-style TS (export =) files fed straight into the estree conversion.","solutions":["Run swc's TypeScript strip pass (swc_ecma_transforms_typescript strip / @swc/core with typescript syntax stripping) before babelify so TS module decls become plain ESM/CJS","Reject or skip TS inputs that use import-equals/export-assignment before conversion","If you need TS output, babelify per-item and handle ModuleDeclOutput::Ts* variants yourself instead of using the ModuleDeclaration From impl","As a stopgap, wrap the conversion in catch_unwind and report the offending file"],"exampleFix":"// before: TS module babelified directly\nlet program = parse_ts_as_module(fm)?;\nlet babel_ast = program.babelify(&ctx); // panics on `import x = require(...)`\n\n// after: strip TypeScript first\nlet program = strip_types(parse_ts_as_module(fm)?)?;\nlet babel_ast = program.babelify(&ctx);","handlingStrategy":"validation","validationCode":"fn module_babelifiable(module: &Module) -> Result<(), String> {\n    for item in &module.body {\n        if let ModuleItem::ModuleDecl(d) = item {\n            let ts = matches!(\n                d,\n                ModuleDecl::TsImportEquals(_) | ModuleDecl::TsExportAssignment(_) | ModuleDecl::TsNamespaceExport(_)\n            );\n            if ts {\n                return Err(\"module uses TS import-equals/export-assignment; strip types first\".into());\n            }\n        }\n    }\n    Ok(())\n}","typeGuard":"fn module_decl_is_plain_esm(d: &ModuleDecl) -> bool {\n    !matches!(d, ModuleDecl::TsImportEquals(_) | ModuleDecl::TsExportAssignment(_) | ModuleDecl::TsNamespaceExport(_))\n}","tryCatchPattern":"let out = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| program.babelify(&ctx)))\n    .map_err(|_| anyhow::anyhow!(\"module contains TypeScript module declarations (import = / export = / export namespace)\"))?;","preventionTips":["Strip TypeScript before requesting the Babel AST flavor","Detect `import x = require(...)` and `export =` in inputs and route them through the TS pipeline","Add fixtures with TS module syntax to your conversion tests","Document that babelify targets plain ESM/CJS modules"],"tags":["swc","babelify","panic","typescript","import-equals","export-assignment","module-declaration"],"backgroundTag":"unsupported-typescript-module-syntax","analyzedSha":"5176682b65416c6b5de6b47379ae1588ea3ecb3f","analyzedAt":"2026-08-17T16:16:52.067Z","schemaVersion":2},"datasetVersion":"2026-08-22T14:17:55.899Z"}