- Rollup Plugin Name:
@rollup/plugin-typescript
- Rollup Plugin Version: 12.3.0
Feature Use Case
Careless use of @rollup/plugin-typescript and @rollup/plugin-json together results in broken TypeScript declarations, in a way that’s difficult to detect until after the package is published. A real example of this regression happening twice in the same package:
Here’s a minimal reproducible example:
package.json, tsconfig.json, src/data.json
package.json
{
"name": "rollup-typescript-json-test",
"version": "0.0.0",
"private": true,
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"devDependencies": {
"@rollup/plugin-json": "^6.1.0",
"@rollup/plugin-typescript": "^12.3.0",
"rollup": "^4.61.1",
"typescript": "^6.0.3"
}
}
tsconfig.json
{
"compilerOptions": {
"declaration": true,
"module": "nodenext",
"noEmit": true,
"outDir": "dist",
"rootDir": "src"
}
}
src/data.json
rollup.config.js
import json from "@rollup/plugin-json";
import typescript from "@rollup/plugin-typescript";
export default {
input: "src/index.ts",
plugins: [json(), typescript({ rootDir: "src" })],
output: { dir: "dist", preserveModules: true },
};
src/index.ts
import data from "./data.json" with { type: "json" };
export { data };
It passes tsc and seemingly builds cleanly with rollup -c, but the resulting type declarations are broken in a way that’s difficult to notice until after publication.
$ npm i
$ npx tsc
$ npx rollup -c
src/index.ts → dist...
created dist in 315ms
$ npx tsc --ignoreConfig --noEmit --module nodenext dist/index.d.ts
dist/index.d.ts:1:18 - error TS2307: Cannot find module './data.json' or its corresponding type declarations.
1 import data from "./data.json";
~~~~~~~~~~~~~
Found 1 error in dist/index.d.ts:1
$ npx tsc --ignoreConfig --noEmit dist/index.d.ts
dist/index.d.ts:1:18 - error TS7016: Could not find a declaration file for module './data.json'. '/home/anders/zulip/test/plugin-typescript-dts-json-repro/dist/data.json.js' implicitly has an 'any' type.
1 import data from "./data.json";
~~~~~~~~~~~~~
Found 1 error in dist/index.d.ts:1
dist/data.json.js, dist/index.d.ts, dist/index.js
dist/data.json.js
var data = [
0,
1,
2
];
export { data as default };
dist/index.d.ts
import data from "./data.json";
export { data };
dist/index.js
export { default as data } from './data.json.js';
The emitted declarations point to a nonexistent dist/data.json. The problem is that @rollup/plugin-json has emitted dist/data.json.js rather than dist/data.json, but TypeScript has no way to know this and couldn’t use dist/data.json.js even if it knew.
One way to discover this problem is using @arethetypeswrong/cli:
$ npx @arethetypeswrong/cli --pack .
rollup-typescript-json-test v0.0.0
Build tools:
- typescript@^6.0.3
- rollup@^4.61.1
- @rollup/plugin-typescript@^12.3.0
⚠️ A require call resolved to an ESM JavaScript file, which is an error in Node and some bundlers. CommonJS consumers will need to use a dynamic import. https://github.com/arethetypeswrong/arethetypeswrong.github.io/blob/main/docs/problems/CJSResolvesToESM.md
🥴 Import found in a type declaration file failed to resolve. Either this indicates that runtime resolution errors will occur, or (more likely) the types misrepresent the contents of the JavaScript files. Use -f json to see the imports that failed to resolve. https://github.com/arethetypeswrong/arethetypeswrong.github.io/blob/main/docs/problems/InternalResolutionError.md
┌───────────────────┬───────────────────────────────┐
│ │ "rollup-typescript-json-test" │
├───────────────────┼───────────────────────────────┤
│ node10 │ 🟢 │
├───────────────────┼───────────────────────────────┤
│ node16 (from CJS) │ ⚠️ ESM (dynamic import only) │
│ │ 🥴 Internal resolution error │
├───────────────────┼───────────────────────────────┤
│ node16 (from ESM) │ 🥴 Internal resolution error │
├───────────────────┼───────────────────────────────┤
│ bundler │ 🟢 │
└───────────────────┴───────────────────────────────┘
But @arethetypeswrong/cli isn’t used nearly as widely as it should be, so it would be better if @rollup/plugin-typescript could somehow detect this problem before it happens.
Feature Proposal
@rollup/plugin-typescript could try to resolve relative imports and re-exports within the emitted declarations against the set of emitted files, and complain if any are missing.
@rollup/plugin-typescriptFeature Use Case
Careless use of
@rollup/plugin-typescriptand@rollup/plugin-jsontogether results in broken TypeScript declarations, in a way that’s difficult to detect until after the package is published. A real example of this regression happening twice in the same package:Here’s a minimal reproducible example:
package.json,tsconfig.json,src/data.jsonpackage.json{ "name": "rollup-typescript-json-test", "version": "0.0.0", "private": true, "type": "module", "main": "dist/index.js", "types": "dist/index.d.ts", "devDependencies": { "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-typescript": "^12.3.0", "rollup": "^4.61.1", "typescript": "^6.0.3" } }tsconfig.json{ "compilerOptions": { "declaration": true, "module": "nodenext", "noEmit": true, "outDir": "dist", "rootDir": "src" } }src/data.jsonrollup.config.jssrc/index.tsIt passes
tscand seemingly builds cleanly withrollup -c, but the resulting type declarations are broken in a way that’s difficult to notice until after publication.dist/data.json.js,dist/index.d.ts,dist/index.jsdist/data.json.jsdist/index.d.tsdist/index.jsThe emitted declarations point to a nonexistent
dist/data.json. The problem is that@rollup/plugin-jsonhas emitteddist/data.json.jsrather thandist/data.json, but TypeScript has no way to know this and couldn’t usedist/data.json.jseven if it knew.One way to discover this problem is using
@arethetypeswrong/cli:But
@arethetypeswrong/cliisn’t used nearly as widely as it should be, so it would be better if@rollup/plugin-typescriptcould somehow detect this problem before it happens.Feature Proposal
@rollup/plugin-typescriptcould try to resolve relativeimports and re-exports within the emitted declarations against the set of emitted files, and complain if any are missing.