Summary
4.0.5 added "type": "module" to package.json (#237), but dist/types/** still emits relative imports without file extensions. Under moduleResolution: node16/nodenext those declaration files are now ESM, where extensionless relative specifiers are not resolvable, so every export of the package fails to type-resolve.
4.0.3 is unaffected — without the "type" field the declarations were interpreted as CJS, where extension inference applies.
Reproduction
// src/index.ts
import { Graph, alg } from "@dagrejs/graphlib";
const g = new Graph();
g.setEdge("a", "b");
console.log(alg.isAcyclic(g));
With @dagrejs/graphlib@4.0.5:
node_modules/@dagrejs/graphlib/dist/types/index.d.ts(30,23): 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.
node_modules/@dagrejs/graphlib/dist/types/index.d.ts(31,25): error TS2834: ...
node_modules/@dagrejs/graphlib/dist/types/index.d.ts(32,23): error TS2834: ...
node_modules/@dagrejs/graphlib/dist/types/index.d.ts(33,22): error TS2834: ...
With @dagrejs/graphlib@4.0.3: clean.
Cause
dist/types/index.d.ts in 4.0.5:
export { Graph } from './lib/graph';
export { version } from './lib/version';
export * as json from './lib/json';
export * as alg from './lib/alg/index';
export type { GraphOptions, Edge, Path, WeightFunction, EdgeFunction, Label } from './lib/types.js';
Only the last line carries .js — because the corresponding source import was written with the extension. The other four are emitted verbatim from extensionless source imports. 5 of the 24 .d.ts files under dist/types/ are affected (index.d.ts, lib/json.d.ts, lib/alg/index.d.ts, and others re-exporting siblings).
The runtime bundles are fine; this is limited to the declaration output.
Why this may not have shown up in testing
skipLibCheck: true — the default in most project templates — suppresses TS2834 entirely. The imports still fail to resolve, so Graph, json and alg silently become any rather than erroring. Consumers get no compile error, just erased types. It surfaces loudly only under skipLibCheck: false, or through type-aware lint rules: in our case @typescript-eslint/no-unsafe-call, no-unsafe-member-access and no-unsafe-assignment fired on every graphlib call site while tsc stayed green.
That combination means the blast radius is likely wider than the issue tracker suggests — most affected consumers would see degraded types rather than a failure.
Suggested fix
Either:
- Add explicit
.js extensions to the relative imports in src/, so tsc emits resolvable specifiers into dist/types/ (matches what lib/types.js already does); or
- Emit a CommonJS-flavoured declaration build alongside the ESM one and point
exports["."].require.types at it.
Option 1 is the smaller change and fixes both the ESM and CJS resolution paths at once.
Versions
@dagrejs/graphlib 4.0.5 (broken), 4.0.3 (fine)
- TypeScript 7.0.2; also reproduces on 6.x
moduleResolution: NodeNext
Summary
4.0.5 added
"type": "module"topackage.json(#237), butdist/types/**still emits relative imports without file extensions. UndermoduleResolution: node16/nodenextthose declaration files are now ESM, where extensionless relative specifiers are not resolvable, so every export of the package fails to type-resolve.4.0.3 is unaffected — without the
"type"field the declarations were interpreted as CJS, where extension inference applies.Reproduction
With
@dagrejs/graphlib@4.0.5:With
@dagrejs/graphlib@4.0.3: clean.Cause
dist/types/index.d.tsin 4.0.5:Only the last line carries
.js— because the corresponding source import was written with the extension. The other four are emitted verbatim from extensionless source imports. 5 of the 24.d.tsfiles underdist/types/are affected (index.d.ts,lib/json.d.ts,lib/alg/index.d.ts, and others re-exporting siblings).The runtime bundles are fine; this is limited to the declaration output.
Why this may not have shown up in testing
skipLibCheck: true— the default in most project templates — suppresses TS2834 entirely. The imports still fail to resolve, soGraph,jsonandalgsilently becomeanyrather than erroring. Consumers get no compile error, just erased types. It surfaces loudly only underskipLibCheck: false, or through type-aware lint rules: in our case@typescript-eslint/no-unsafe-call,no-unsafe-member-accessandno-unsafe-assignmentfired on every graphlib call site whiletscstayed green.That combination means the blast radius is likely wider than the issue tracker suggests — most affected consumers would see degraded types rather than a failure.
Suggested fix
Either:
.jsextensions to the relative imports insrc/, sotscemits resolvable specifiers intodist/types/(matches whatlib/types.jsalready does); orexports["."].require.typesat it.Option 1 is the smaller change and fixes both the ESM and CJS resolution paths at once.
Versions
@dagrejs/graphlib4.0.5 (broken), 4.0.3 (fine)moduleResolution: NodeNext