`genType` emits relative `./S.gen` for workspace (file:) dependencies instead of package-qualified sury/src/S.gen

Đang mở
#8,375 1 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

Đánh giá

Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức phù hợp với người mới
58/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Ít trao đổi
Công nghệ
node.js, ocaml, typescript
Lĩnh vực
build-system, compilers

Hướng nghiên cứu

Bắt đầu trong compiler/gentype/ModuleResolver.ml, đặc biệt là resolve_module, import_path_for_reason_module_name và read_bs_dependencies_dirs, sau đó kiểm tra compiler/gentype/ImportPath.ml. Tái hiện bằng pnpm workspace được mô tả và chạy tsc --noEmit. Được xem là hoàn thành khi import được sinh ra sử dụng đường dẫn lib/src/S.gen có đủ định danh package cho các dependency file: và bước kiểm tra kiểu chạy qua mà không cần shim.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

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 on 12.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.json correctly lists ["lib", "/abs/path/packages/lib"] under "pkgs", so the dependency is known to the build.
  • Poking at the bsc.exe strings, the relevant logic lives in compiler/gentype/ModuleResolver.ml (resolve_module, import_path_for_reason_module_name, read_bs_dependencies_dirs) and compiler/gentype/ImportPath.ml.
  • It looks like when the dep's source directory is reachable via a workspace path, the resolver adds S to the consumer's local module_name_map and that takes precedence over the dep lookup, so the import is emitted relative.
  • No gentypeconfig option currently works around this: shims treats its value as a shim-file path (emits ./lib/src/S.gen.shim), and there's no packageName / importPath / modulesMap option 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.

Ngôn ngữ chính
OCaml
Star
7.5k
Fork
485
Merge trung bình
1 ngày 2 giờ
Pull request đã merge (30 ngày)
55

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của rescript-lang/rescript

Tất cả issue của rescript-lang/rescript

Issue tương tự

Thêm issue về Build System

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.