This project attempts to analyze npm package contents for issues with their TypeScript types, particularly ESM-related module resolution issues. Currently, the following kinds of problems can be detected in the node10, node16, and bundler module resolution modes:
exports) fails to resolve completely. This will result in a TypeScript compiler error, and may indicate that the runtime corresponding to the module resolution mode tested might fail to resolve it too.noImplicitAny.node16 resolution mode, TypeScript detects whether Node itself will assume a file is a CommonJS or ECMAScript module. If the types resolved are detected to be CJS, but the JavaScript resolved is detected to be ESM, this problem is raised. It is often caused by a dependency’s package.json doing something like:
json
{
"exports": {
"types": "./index.d.ts",
"import": "./index.mjs",
"require": "./index.js"
}
}
Because there is no "type": "module" setting here, the .js and .d.ts file will always be interpreted as a CommonJS module. But if the importing file is an ES module, the runtime will resolve to the .mjs file, which is unambiguously ESM. In this case, the module kind of the types misrepresents the runtime-resolved module. This tends to present the most issues for users when default exports are used. In the future, this tool may detect whether an export default might make this problem more severe and give a full explanation of why. In the meantime, you can read the explanation in this issue. The simple fix for the example above would be to add an index.d.mts file dedicated to typing the .mjs module, and remove the "types" condition."type": "module", and the importing file is a CJS module.type. If these signal that the file is ESM, module and require will be undefined. If they signal that the file is CJS, import and export statements will be syntax errors. This problem is raised when syntax incompatible with the detected module kind is used.node16 resolves to an ES module (and not falsely so, as above, as far as we can tell). This is a TypeScript compiler error and will be a runtime error in Node. It’s not necessarily a defect of the package; it likely just means that the author decided to only publish ESM, leaving their CommonJS consumers without a good option."exports" in a package.json, it tries to resolve with the first matching condition. If resolution fails with that condition, the process is over and the import is not resolved. TypeScript’s algorithm instead continues through the list of conditions and attempts to resolve with any other condition that matches, until resolution succeeds or the no more conditions match. This is a TypeScript bug, so its behavior should not be relied upon—even if the bug never gets fixed, results that arise from it are likely to be innacurate since the resolution process diverges from Node.module.exports.default instead of its module.exports by setting module.exports.__esModule to true. Node does not respect the __esModule marker, though, so default imports of the file in Node will have to add an additional .default property access in order to get to the file’s intended default export:
ts
// main.mts:
import doSomething from "dependency";
doSomething(); // doesn't work
doSomething.default(); // works
This problem is reported when a CJS module appears to use module.exports.default, has an __esModule marker, and its types use export default. It’s important to notice that in this case, the types and the implementation agree. Adding a .default is necessary, both to run in Node and to satisfy the TypeScript compiler. There are no inconsistencies here, but the pattern is discouraged since the code needed to use the import in a bundler and the code needed in Node are mutually incompatible. Instead, the library is encouraged to use module.exports instead of, or in addition to, module.exports.default. So no, the types aren’t wrong, but the package likely isn’t functioning in Node like they intended.module.exports = but its types use export default. The correct type declaration for module.exports = ... is export = .... This mismatch doesn’t usually present a problem in bundlers, but for Node, TypeScript will falsely think a default import from an ESM file needs an additional .default, as in the example from the previous problem.The first things on my roadmap:
Some other ideas:
$ claude mcp add arethetypeswrong.github.io \
-- python -m otcore.mcp_server <graph>