Skip to content

Fix CommonJS type export so the default import resolves under node16/nodenext - #47

Merged
samclarke merged 1 commit into
samclarke:masterfrom
markedwards:fix/cjs-type-export
Aug 7, 2026
Merged

Fix CommonJS type export so the default import resolves under node16/nodenext#47
samclarke merged 1 commit into
samclarke:masterfrom
markedwards:fix/cjs-type-export

Conversation

@markedwards

Copy link
Copy Markdown
Contributor

Backwards compatibility: No breaking change — existing code keeps working. Today the types resolve to any, so there's no real type contract to break; this just makes import/require correctly typed. Safe as a patch release.

Problem

index.d.ts doesn't match the runtime. index.js is CommonJS:

module.exports = function (url, contents) { ... };

but the types say:

declare module 'robots-parser';                     // (1)
export default function robotsParser(...): Robot;   // (2)
  1. declare module 'robots-parser'; has an empty body, so TypeScript types the whole module as any. The Robot interface right below it is never applied to what you import — every consumer gets any today.
  2. export default doesn't describe module.exports = fn. Under moduleResolution: node16 / nodenext (the modern default), the default import doesn't line up with the CommonJS export.

Fix

Describe the actual CommonJS shape. One file, no runtime change:

declare function robotsParser(url: string, robotstxt: string): Robot;

export = robotsParser;

Why this doesn't need a major version bump

Because declare module 'robots-parser'; currently resolves the module to any, no one has working type-checking against this package today. This PR adds accurate types over what was effectively untyped — it can't break a type contract that never existed.

Every import style that works today keeps working:

Import style Today After
import r from 'robots-parser' (with esModuleInterop, or node16/nodenext) any typed function
import r = require('robots-parser') any typed function
const r = require('robots-parser') works works

The only case that changes is import r from 'robots-parser' with esModuleInterop: false on classic module resolution — which is already broken at runtime (module.exports has no .default, so r is undefined). After this change that becomes a clear compile error pointing to import r = require('robots-parser'), instead of failing silently.

Strictly better types, nothing that currently type-checks breaks → patch release.

`index.js` is CommonJS (`module.exports = fn`), but `index.d.ts` typed it
as an ES `export default` alongside an empty `declare module 'robots-parser';`.

The empty ambient declaration types the whole module as `any`, so the
`Robot` interface is never actually applied. And `export default` does not
describe `module.exports = fn` under `moduleResolution: node16`/`nodenext`.

Replace both with `export = robotsParser`, matching the runtime. No code
changes. Since the module currently resolves to `any`, this only adds
accurate types and breaks nothing that type-checks today.
@samclarke
samclarke merged commit fc27a00 into samclarke:master Aug 7, 2026
11 checks passed
@samclarke

Copy link
Copy Markdown
Owner

Thanks for the PR! 👍

Looks to be the right way based on the TypeScript docs. Merged, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants