Skip to content

@rollup/plugin-typescript should error on TypeScript import of missing .json file (bundled with a different name by @rollup/plugin-json) #2008

@andersk

Description

@andersk
  • 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

[0, 1, 2]

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions