rescript-lang / rescript-lang/rescript
`genType` emits relative `./S.gen` for workspace (file:) dependencies instead of package-qualified sury/src/S.gen
Dieses Issue hat noch niemand übernommen.
- Vorherrschende Sprache
- OCaml
- Sterne
- 7.5k
- Forks
- 485
- Ø Merge
- 1 T. 2 Std.
- Gemergte PRs (30 T.)
- 55
Beschreibung
Summary
When a consumer package depends on another package via a pnpm/npm workspace file: link, genType emits the import path for cross-package types as a relative path (./S.gen) instead of the package-qualified path (sury/src/S.gen). The relative path does not resolve — there's no S.gen.{ts,d.ts} next to the generated file — so downstream tsc fails with TS2307: Cannot find module './S.gen'.
Versions
rescript:12.2.0(also reproduces on12.0.0-beta.5)- Package manager:
pnpm@9.0.5 - Node:
22.6.0 - OS: Ubuntu 24.04
Minimal repro
Two-package pnpm workspace. lib publishes hand-written S.gen.d.ts; app imports its type via @genType.
repro/
├─ pnpm-workspace.yaml # packages: ["packages/*"]
├─ packages/
│ ├─ lib/
│ │ ├─ package.json # { "name": "lib" }
│ │ ├─ rescript.json # below
│ │ └─ src/
│ │ ├─ S.res # let string: t<string> ; type error = {…}
│ │ └─ S.gen.d.ts # hand-written: export type t<T> = …; export type error = …
│ └─ app/
│ ├─ package.json # { "dependencies": { "lib": "file:../lib" } }
│ ├─ rescript.json # below
│ └─ src/
│ └─ Demo.res # @genType let x: S.error = …
packages/lib/rescript.json:
{
"name": "lib",
"namespace": false,
"suffix": ".res.mjs",
"package-specs": { "module": "esmodule", "in-source": true },
"sources": [{ "dir": "src", "public": ["S"] }]
}
packages/app/rescript.json:
{
"name": "app",
"sources": [{ "dir": "src", "subdirs": true }],
"package-specs": { "module": "esmodule", "in-source": true },
"suffix": ".res.mjs",
"dependencies": ["lib"],
"gentypeconfig": { "generatedFileExtension": ".gen.ts" }
}
packages/app/src/Demo.res:
@genType
let err: S.error = S.Error.make(…)
Run pnpm install && pnpm --filter=app rescript build.
Actual output
packages/app/src/Demo.gen.ts:
import type {error as S_error} from './S.gen'; // ❌ relative — no such file next to Demo.gen.ts
tsc --noEmit reports:
Demo.gen.ts(…,…): error TS2307: Cannot find module './S.gen' or its corresponding type declarations.
Expected output
import type {error as S_error} from 'lib/src/S.gen';
(This was the behavior in earlier versions — the same repo has a committed Demo.gen.ts from a prior generation that used from 'lib/src/S.gen'.)
Context / investigation
app/lib/bs/.sourcedirs.jsoncorrectly lists["lib", "/abs/path/packages/lib"]under"pkgs", so the dependency is known to the build.- Poking at the
bsc.exestrings, the relevant logic lives incompiler/gentype/ModuleResolver.ml(resolve_module,import_path_for_reason_module_name,read_bs_dependencies_dirs) andcompiler/gentype/ImportPath.ml. - It looks like when the dep's source directory is reachable via a workspace path, the resolver adds
Sto the consumer's localmodule_name_mapand that takes precedence over the dep lookup, so the import is emitted relative. - No
gentypeconfigoption currently works around this:shimstreats its value as a shim-file path (emits./lib/src/S.gen.shim), and there's nopackageName/importPath/modulesMapoption documented in the bsc binary.
Workaround
Ship a shim next to the generated file that re-exports from the dep:
// packages/app/src/S.gen.ts
export type { error, t } from "lib/src/S.gen";
This keeps the relative ./S.gen import resolving, but is obviously a workaround.
Does it reproduce outside file: deps?
Not when lib is a real npm dependency (resolved under node_modules/lib) — that case emits 'lib/src/S.gen' correctly. Only workspace / file: installs hit this.
Beitragsleitfaden
Erste Schritte
- Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
- Forke das Repository und arbeite in einem Branch.
- Öffne einen Pull Request, der die Issue-Nummer nennt.
Rechercherichtung
Beginne in compiler/gentype/ModuleResolver.ml, insbesondere bei resolve_module, import_path_for_reason_module_name und read_bs_dependencies_dirs, und prüfe anschließend compiler/gentype/ImportPath.ml. Reproduziere das Problem mit dem beschriebenen pnpm workspace und führe tsc --noEmit aus. Erledigt ist die Aufgabe, wenn der generierte Import für file:-Abhängigkeiten den paketqualifizierten Pfad lib/src/S.gen verwendet und die Typprüfung ohne Shim erfolgreich ist.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Bewertung
- Tech-Stack
- node.js, ocaml, typescript
- Bereich
- build-system, compilers
- Issue-Typ
- Bug
- Schwierigkeit
- 4/5
- Geschätzter Aufwand
- 3-5 Tage
- Aktivitätsstatus
- Ruhig
- Klarheit
- Klar beschrieben
- Anfängerfreundlichkeit
- 58/100