microsoft / microsoft/TypeScript

Project references resolve a symlinked sibling's raw source instead of its own composite output, using the wrong project's compilerOptions

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

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

Needs More Info
Ngôn ngữ chính
Go
Star
111k
Fork
14.3k
Merge trung bình
2 ngày 4 giờ
Pull request đã merge (30 ngày)
132

Mô tả

Acknowledgement
  • #63744
Comment

Project references resolve a symlinked sibling's raw source instead of its own composite output, using the wrong project's compilerOptions

Repo: Microsoft/TypeScript

TypeScript version: 6.0.3 (via Bun 1.3.14)

OS: Debian GNU/Linux 13 (trixie)
Kernel: Linux 6.12.96+deb13-amd64
Arch: x86_64

Summary

In a --build (tsc -b) solution with project references, when Project A's compiled .d.ts output re-exports a type from Project B, and Project B is reachable from node_modules only via a symlink, TypeScript resolves that re-exported type by reading Project B's raw .ts source under a foreign project's compilerOptions, not Project B's own. This causes real, valid source files to fail type-checking with missing ambient globals (Buffer, process, Bun, fs, dns, setImmediate) that are correctly declared via Project B's own "types" field.

Confirmed not package-manager-specific

Filed a companion report against Bun (oven-sh/bun) first, since symlinked node_modules/dann-sdk was the entry point observed. A Bun maintainer confirmed:

Workspace members are always linked as symlinks, under both linkers. Hoisted: node_modules/pkg-a -> ../packages/a. Isolated: packages/b/node_modules/pkg-a -> ../../a. This is intentional and matches npm, yarn, and pnpm workspace behavior.

npm, yarn, and pnpm all symlink workspace-local sibling packages by default, the same as Bun. This means any project using TypeScript project references inside an npm, yarn, pnpm, or Bun workspace, where one package's compiled output re-exports a type from a sibling package, is a candidate for this bug. It is not a Bun quirk, it is a general symlink plus project-references interaction in TypeScript itself.

Repro

Minimal shape:

packages/
  sdk/
    tsconfig.json      # "types": ["bun"], "composite": true
    src/utils/settings-crypto.ts   # uses Buffer, crypto (from @types/bun)
  trace/
    tsconfig.json      # "composite": true, "outDir": "./dist"
    kernel-log.ts      # re-exports a type from sdk: `import type { LogCtx } from 'dann-sdk'`
  leaf/
    tsconfig.json      # references: [{ "path": "../trace" }]
    # leaf's own source never imports sdk directly

Root package.json:

{
  "workspaces": ["packages/*"]
}

Steps:

  1. Install with any workspace-aware package manager (npm, yarn, pnpm, or Bun). Local packages get symlinked into node_modules.
  2. tsc -b packages/trace/tsconfig.json, succeeds, emits packages/trace/dist/kernel-log.d.ts containing import("dann-sdk").LogCtx.
  3. tsc -b packages/leaf/tsconfig.json --listFiles, even though leaf's own source and its declared references never touch sdk, the file list includes about 76 files under packages/sdk/, and errors appear for sdk's own source files:
    packages/sdk/src/utils/settings-crypto.ts(8,20): error TS2591: Cannot find name 'crypto'.
    packages/sdk/src/utils/mem-checkpoint.ts(31,14): error TS2868: Cannot find name 'Bun'.
    
  4. tsc -b packages/sdk/tsconfig.json run standalone: exit 0, no errors. Same files, same compilerOptions, correct when built directly.

Root cause (as far as traced)

node_modules/dann-sdk is a symlink to packages/sdk (standard workspace linking, confirmed universal across npm, yarn, pnpm, and Bun). When TypeScript resolves the bare specifier "dann-sdk" from inside packages/trace/dist/kernel-log.d.ts, it walks up through node_modules, finds the symlink, and since the symlink's real path is identical to a project already known via references elsewhere in the graph, appears to fold sdk's raw source into whichever project's compilation triggered that resolution, instead of routing it through sdk's own composite project boundary. The same files compiled through their own tsconfig.json are clean.

Tried and ruled out

  • disableSourceOfProjectReferenceRedirect: true on the referencing project (trace): no change.
  • disableSourceOfProjectReferenceRedirect: true on the referenced project (sdk, where the docs say it belongs): no change.
  • Explicit paths remapping of dann-sdk to source across every referencing project's tsconfig.json (mirroring an existing working pattern used elsewhere in the same repo for three other packages that do not trigger this bug): no change.
  • Deleting all .tsbuildinfo and forcing a full rebuild (--force): no change, rules out stale incremental cache.
  • Confirmed not an artifact of accumulated dist/ output from repeated test runs: reproduced from a completely fresh clone, fresh install, first ever build.
  • Confirmed not fixable at the package manager level: symlinked workspace members are intentional and universal across npm, yarn, pnpm, and Bun (see maintainer confirmation above). A file: dependency kept out of the workspaces glob installs as a real physical directory instead of a symlink and does not trigger the bug, but that gives up live workspace linking entirely, it is a workaround, not a fix.

Expected: sdk's files should only ever be type-checked under sdk's own compilerOptions, regardless of which symlinked path led TypeScript to them.

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.

Hướng nghiên cứu

Bắt đầu bằng cách tái hiện vấn đề với các tệp packages/trace, packages/leaf và packages/sdk tsconfig.json, sử dụng tsc -b và --listFiles. Kiểm tra cách import trong packages/trace/dist/kernel-log.d.ts được phân giải thông qua gói node_modules được liên kết bằng symbolic link và cách các tham chiếu dự án chọn compilerOptions. Hoàn tất có nghĩa là mã nguồn sdk chỉ được kiểm tra bằng các tùy chọn của sdk khi build leaf, không có các lỗi ambient-global đã báo cáo.

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

Đánh giá

Công nghệ
typescript
Lĩnh vực
compilers
Loại issue
Lỗi
Độ khó
5/5
Thời gian dự kiến
Hơn một tuần
Mức độ hoạt động
Ít trao đổi
Độ rõ ràng
Khá rõ ràng
Mức phù hợp với người mới
35/100

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.