Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Feb 7, 2026

tsgo silently emits files next to source instead of outDir when include references parent directories (e.g., ../common/src/**/*). The submodule TypeScript 6.0 has the same output path behavior but emits TS5011 telling the user to set rootDir explicitly. The Go port was missing this diagnostic entirely, making the misconfiguration invisible.

Changes

  • internal/outputpaths/commonsourcedirectory.go: Added GetComputedCommonSourceDirectory — public wrapper matching TypeScript's getComputedCommonSourceDirectory, computes common source dir from file list rather than config file path
  • internal/compiler/program.go: Implemented the TS5011 migration check from TypeScript 6.0. When !noEmit && !composite && !rootDir && configFilePath && (outDir || declarationDir || outFile), compares the config-file-based common source directory against the file-computed one. If they differ, emits TS5011 with chained migration URL diagnostic
  • internal/execute/tsctests/tsc_test.go: Added TestTscOutDirWithParentDirInclude reproducing the reported scenario
  • Baselines: Updated to reflect TS5011 now firing for non-composite projects where computed common source dir differs from config file dir

Repro

// sub/tsconfig.json
{
  "extends": "../tsconfig.json",
  "include": ["src/**/*", "../common/src/**/*"]
}

Before: common/src/greeter.js emitted next to source with exit code 0.
After: TS5011 error emitted matching submodule TypeScript behavior.

Original prompt

This section details on the original issue you should resolve

<issue_title>tsgo emits files next to source instead of outDir when include references parent directories via ../</issue_title>
<issue_description>## Steps to reproduce

  1. Clone the minimal repro: https://github.com/Cellule/tsgo-outdir-repro
  2. Run npx --package=@typescript/native-preview@7.0.0-dev.20260130.1 tsgo -p sub/tsconfig.json
  3. Observe that common/src/greeter.js is emitted next to the source file instead of in sub/dist/

Project structure

.
├── tsconfig.json            # parent config with outDir: "${configDir}/dist/"
├── common/src/greeter.ts    # shared source file
└── sub/
    ├── tsconfig.json        # extends ../tsconfig.json, includes ../common/src/**/*
    └── src/index.ts         # imports from ../../common/src/greeter.js

tsconfig.json (root):

{
  "compilerOptions": {
    "target": "ES2024",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "outDir": "${configDir}/dist/",
    "strict": true,
    "skipLibCheck": true
  },
  "include": ["common/src/**/*"]
}

sub/tsconfig.json:

{
  "extends": "../tsconfig.json",
  "include": [
    "src/**/*",
    "../common/src/**/*"
  ]
}

Behavior with typescript@5.9

All output files are correctly placed in sub/dist/:

$ npx --package=typescript@5.9 tsc -p sub/tsconfig.json && find . -name '*.js' -not -path '*/node_modules/*'
./sub/dist/sub/src/index.js
./sub/dist/common/src/greeter.js

Behavior with tsgo (@typescript/native-preview@7.0.0-dev.20260130.1)

Files from parent directories (included via ../) are emitted next to the source files instead of in outDir:

$ npx --package=@typescript/native-preview@7.0.0-dev.20260130.1 tsgo -p sub/tsconfig.json && find . -name '*.js' -not -path '*/node_modules/*'
./sub/dist/src/index.js      # file inside sub/ goes to sub/dist/ ✅
./common/src/greeter.js      # file outside sub/ emitted next to source ❌

Note: --showConfig reports the correct resolved outDir:

"outDir": "/path/to/sub/dist"

Bisect result

  • Last good version: 7.0.0-dev.20260109.1
  • First bad version: 7.0.0-dev.20260111.1

The regression was introduced between these two nightly builds. The 5 commits in that range are:

  1. 2a31979f — Preallocate types slice in getLiteralTypeFromProperties (Preallocate types slice in getLiteralTypeFromProperties #2458)
  2. 38353bd4 — New auto-import infrastructure (New auto-import infrastructure #2390)
  3. 43313db8 — Also clean CI runner for smoke test (Also clean CI runner for smoke test #2464)
  4. 0f7cc3dd — Handle long paths in native-preview tsgo entrypoint (Handle long paths in native-preview tsgo entrypoint #2448)
  5. 6e1e2c29 — Cache types computed by getLiteralTypeFromProperties (Cache types computed by getLiteralTypeFromProperties #2466)

The most likely culprit is #2390 as the only substantial change touching the compiler.

Additional notes

  • The issue is not specific to ${configDir} — using "outDir": "./dist/" produces the same result
  • Setting rootDir explicitly does not fix it
  • The issue occurs both with and without --build
  • The issue also affects the latest nightly (7.0.0-dev.20260206.1)</issue_description>

<agent_instructions>Make a compiler test or tsctest out of https://github.com/Cellule/tsgo-outdir-repro. Do not do anything else until you have a test case which reproduces the issue. COMMIT THAT, then fix the issue.</agent_instructions>

Comments on the Issue (you are @copilot in this section)

@jakebailey Can you please compare against the 6.0 nightly instead of 5.9? @jakebailey (I was assuming it was rootDir, but it probably isn't)

💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 2 commits February 7, 2026 16:39
…udes

Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
…match

When a non-composite project uses configFilePath to determine the common
source directory, and the computed common source directory from files
differs, emit TS5011 telling the user to explicitly set rootDir. This
matches the submodule TypeScript 6.0 behavior.

Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix tsgo emitting files next to source instead of outDir Implement TS5011 migration diagnostic for common source directory mismatch Feb 7, 2026
Copilot AI requested a review from jakebailey February 7, 2026 17:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

tsgo emits files next to source instead of outDir when include references parent directories via ../

2 participants