{"record":{"id":"d4bb0fb6333fdf5f","repo":"facebook/flow","slug":"commonjs-exports-cannot-be-combined-with-es-module","errorCode":null,"errorMessage":"CommonJS exports cannot be combined with ES module exports.","messagePattern":"CommonJS exports cannot be combined with ES module exports\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/flow-api-translator/src/flowDefToTSDef.js","lineNumber":2007,"sourceCode":"      | [\n          TSESTree.VariableDeclaration,\n          TSESTree.TSTypeAliasDeclaration,\n          TSESTree.TSExportAssignment,\n        ] {\n      // TS forbids `export = ` in a module that has any other export, so a\n      // module combining the two has no faithful translation.\n      if (\n        node.parent.type === 'Program' &&\n        node.parent.body.some(\n          statement =>\n            statement.type === 'DeclareExportAllDeclaration' ||\n            statement.type === 'DeclareExportDeclaration' ||\n            statement.type === 'ExportAllDeclaration' ||\n            statement.type === 'ExportDefaultDeclaration' ||\n            statement.type === 'ExportNamedDeclaration',\n        )\n      ) {\n        throw translationError(\n          node,\n          'CommonJS exports cannot be combined with ES module exports.',\n        );\n      }\n\n      // `declare module.exports: T` is TS's `export = <value>`, which - like\n      // `export default` - can only name a value.\n      const type = node.typeAnnotation.typeAnnotation;\n\n      if (\n        type.type === 'TypeofTypeAnnotation' &&\n        type.argument.type === 'Identifier' &&\n        isDeclaredClass(type.argument.name)\n      ) {\n        return {\n          type: 'TSExportAssignment',\n          loc: DUMMY_LOC,\n          expression: {","sourceCodeStart":1989,"sourceCodeEnd":2025,"githubUrl":"https://github.com/facebook/flow/blob/5c865861998a8ccb7dbc82b0c1f511e9ef60c3d9/packages/flow-api-translator/src/flowDefToTSDef.js#L1989-L2025","documentation":"flowDefToTSDef throws this translationError when a Flow libdef module mixes CommonJS exports (declare module.exports) with ES-module-style export declarations (ExportAllDeclaration, ExportDefaultDeclaration, ExportNamedDeclaration, or DeclareExportDeclaration) in the same file. TypeScript cannot express both `export =` and ES export syntax for one module, so the translator refuses the input rather than emitting invalid TS.","triggerScenarios":"Running flowDefToTSDef on a Flow libdef file whose top-level statement list contains both a `declare module.exports` statement and any ES-style export declaration node.","commonSituations":"Hand-edited or auto-merged libdefs that combined legacy `declare module.exports: T` CommonJS form with modern `declare export ...` statements; converting old libdefs to the newer ES syntax and leaving both forms in place; copy-pasting export blocks between libdef files.","solutions":["Remove one export style from the libdef: if it uses `declare module.exports`, delete the ES export declarations (and vice versa).","Migrate the whole file to ES module syntax: replace `declare module.exports: T` with `declare export default T` or named `declare export` statements.","Split the module into two files if some exports are genuinely CommonJS and others ES-style.","Re-run the translator after fixing to confirm the libdef converts cleanly."],"exampleFix":"// before (libdef)\ndeclare module.exports: number;\ndeclare export foo(): void;\n// after\ndeclare export default number;\ndeclare export foo(): void;","handlingStrategy":"validation","validationCode":"function hasMixedExports(body) {\n  const cjs = body.some(s => s.type === 'DeclareModuleExports');\n  const es = body.some(s =>\n    ['DeclareExportDeclaration', 'ExportAllDeclaration', 'ExportDefaultDeclaration', 'ExportNamedDeclaration'].includes(s.type));\n  return cjs && es; // true => translator will throw; fix the file first\n}","typeGuard":"function isPureEsModule(body) {\n  return !body.some(s => s.type === 'DeclareModuleExports');\n}","tryCatchPattern":"try {\n  const tsDef = flowDefToTSDef(ast);\n} catch (e) {\n  if (String(e.message).includes('CommonJS exports cannot be combined')) {\n    console.error('Libdef mixes module.exports with ES exports; rewrite as pure ES module.');\n  }\n  throw e;\n}","preventionTips":["Pick one export style per libdef file; prefer modern `declare export` syntax.","Add a lint/AST check that rejects DeclareModuleExports alongside export declarations.","When migrating legacy libdefs, remove `declare module.exports` in the same change that adds ES exports.","Run flowDefToTSDef in CI so mixed-export libdefs are caught before release."],"tags":["javascript","typescript","flow","libdef","module-exports","translation"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"5c865861998a8ccb7dbc82b0c1f511e9ef60c3d9","analyzedAt":"2026-09-08T04:32:53.179Z","contentChangedAt":"2026-09-08T04:32:53.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}