facebook/flow · error
CommonJS exports cannot be combined with ES module exports.
Error message
CommonJS exports cannot be combined with ES module exports.
What it means
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.
Source
Thrown at packages/flow-api-translator/src/flowDefToTSDef.js:2007
| [
TSESTree.VariableDeclaration,
TSESTree.TSTypeAliasDeclaration,
TSESTree.TSExportAssignment,
] {
// TS forbids `export = ` in a module that has any other export, so a
// module combining the two has no faithful translation.
if (
node.parent.type === 'Program' &&
node.parent.body.some(
statement =>
statement.type === 'DeclareExportAllDeclaration' ||
statement.type === 'DeclareExportDeclaration' ||
statement.type === 'ExportAllDeclaration' ||
statement.type === 'ExportDefaultDeclaration' ||
statement.type === 'ExportNamedDeclaration',
)
) {
throw translationError(
node,
'CommonJS exports cannot be combined with ES module exports.',
);
}
// `declare module.exports: T` is TS's `export = <value>`, which - like
// `export default` - can only name a value.
const type = node.typeAnnotation.typeAnnotation;
if (
type.type === 'TypeofTypeAnnotation' &&
type.argument.type === 'Identifier' &&
isDeclaredClass(type.argument.name)
) {
return {
type: 'TSExportAssignment',
loc: DUMMY_LOC,
expression: {View on GitHub (pinned to 5c86586199)
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.
Example fix
// before (libdef) declare module.exports: number; declare export foo(): void; // after declare export default number; declare export foo(): void;
Defensive patterns
Strategy: validation
Validate before calling
function hasMixedExports(body) {
const cjs = body.some(s => s.type === 'DeclareModuleExports');
const es = body.some(s =>
['DeclareExportDeclaration', 'ExportAllDeclaration', 'ExportDefaultDeclaration', 'ExportNamedDeclaration'].includes(s.type));
return cjs && es; // true => translator will throw; fix the file first
} Type guard
function isPureEsModule(body) {
return !body.some(s => s.type === 'DeclareModuleExports');
} Try / catch
try {
const tsDef = flowDefToTSDef(ast);
} catch (e) {
if (String(e.message).includes('CommonJS exports cannot be combined')) {
console.error('Libdef mixes module.exports with ES exports; rewrite as pure ES module.');
}
throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Unexpected function parameter ${param.type}
- updatePendingStatements: Variable for dependency "${dep}" no
- updatePendingStatements: Variable parent of "${dep}" not fou
- hermesParse: invalid source_type={other}; expected 0 (unspec
- flowImportTo: Unexpected transform result.
AI-assisted analysis of facebook/flow@5c86586199 (2026-09-08).
Data as JSON: /api/errors/d4bb0fb6333fdf5f.
Report an issue: GitHub.