Skip to content

Type declarations break under moduleResolution: node16/nodenext (extensionless relative imports in ESM .d.ts files) #765

Description

@TheDadi

Summary

@embedpdf/engines and @embedpdf/models (2.15.0) are unusable at the type level in projects using TypeScript's node16/nodenext module resolution. Every named import fails with TS2305 ("has no exported member") even though the API exists and works at runtime.

The published .d.ts tree uses extensionless relative specifiers (export * from './engine') inside packages declared "type": "module". Under node16/nodenext, TypeScript applies ESM resolution rules to those declaration files and requires explicit .js extensions, so every relative re-export fails to resolve and the entry-point modules end up with no members. The runtime JS is bundled into chunks with resolvable specifiers, which is why this only bites the type checker.

Reproduction

// package.json
{ "type": "module", "dependencies": { "@embedpdf/engines": "2.15.0" } }
// tsconfig.json
{ "compilerOptions": { "module": "nodenext", "moduleResolution": "nodenext", "noEmit": true } }
// index.ts
import { PdfEngine, PdfiumNative } from '@embedpdf/engines/pdfium';
import { createNodeImageDataToBufferConverter } from '@embedpdf/engines/converters';
error TS2305: Module '"@embedpdf/engines/pdfium"' has no exported member 'PdfEngine'.
error TS2305: Module '"@embedpdf/engines/pdfium"' has no exported member 'PdfiumNative'.
error TS2305: Module '"@embedpdf/engines/converters"' has no exported member 'createNodeImageDataToBufferConverter'.

Running with --traceResolution shows the underlying failures inside the package's own declaration files, e.g. resolving dist/lib/pdfium/index.d.ts:

error TS2834: Relative import paths need explicit file extensions in ECMAScript imports
when '--moduleResolution' is 'node16' or 'nodenext'. Consider adding an extension to the import path.
...
======== Module name './engine' was not resolved. ========

Reproduced with TypeScript 5.x and 6.0.3.

Root cause

dist/lib/pdfium/index.d.ts (and most of the declaration tree) re-exports without extensions:

export * from './engine';
export * from './helper';
export * from '../converters/types';
export * from '../converters/browser';

Since the package is "type": "module", these .d.ts files are interpreted as ESM, where node16/nodenext requires ./engine.js. In @embedpdf/engines 2.15.0 this affects 45 of the 69 published .d.ts files; @embedpdf/models 2.15.0 has the same problem (10 of 21 files). @embedpdf/pdfium is fine, since its index.d.ts is a single rolled-up file.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions