rootDirs should merge outputs

未關閉
#44,321 3 則留言 5 個 reaction 已指派 0 人 在 GitHub 檢視

還沒有人認領這個 Issue。

評估

難度
5/5
預估耗時
一週以上
新手友好度
35/100
Issue 類型
功能
描述清晰度
基本清楚
活躍度
停滯
技術堆疊
typescript

研究方向

首先檢視編譯器現有的 rootDir 和 rootDirs 行為,以及相關的 issue #9875。預期結果是從輸出的路徑中移除每個已設定的根目錄,讓產生的檔案與原始檔案共用同一個輸出樹狀結構;請使用此處所示的設定與目錄配置驗證此行為。

由索引模型根據 Issue 內容生成。

描述

Awaiting More Feedback Suggestion

Suggestion

🔍 Search Terms

rootDirs merge output

Related: https://github.com/microsoft/TypeScript/issues/9875

✅ Viability Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

⭐ Suggestion

rootDirs should merge outputs instead of emitting to the folders listed in rootDirs. This would be consistent with rootDir.

📃 Motivating Example

Starting point: single root

Let's say I start with a project with a src/ folder:

.
└── src
    ├── index.ts
    ├── lib
    │   └── lib.ts
    └── test
        └── test.ts

It has one rootDir and this config:

{
  "compilerOptions": {
    "outDir": "./",
    "rootDir": "./src",
  },
  "include": ["src/**/*.ts"],
  "exclude": []
}

When I compile, the output goes to ./ and mirrors the structure of ./src:

.
├── lib
│   └── lib.js
├── src
│   ├── index.ts
│   ├── lib
│   │   └── lib.ts
│   └── test
│       └── test.ts
└── test
    └── test.js

All well and good.

Friction point: add generated files

Now I want to add some generated .ts files to my project and keep them outside of src/ for easier source control.

I put a .graphql source file in my src/ tree, and set up the generator to output to gen/:

.
├── gen
│   └── lib
│       └── schema.ts
└── src
    ├── index.ts
    ├── lib
    │   ├── lib.ts
    │   └── schema.graphql
    └── test
        └── test.ts

Now I want the same output structure as before, but I want to compile the sources in gen/ and output them as if I had "rootDir": "./gen".

The first thing I try is to replace "rootDir": "./src" with "rootDirs": ["./src", "./gen"]:

{
  "compilerOptions": {
    "outDir": "./",
    "rootDirs": ["./src", "./gen"],
  },
  "include": ["src/**/*.ts", "gen/**/*.ts"],
  "exclude": []
}

but this unfortunately defaults rootDir to ./, putting src/ and /gen in the output paths and writing .js files as siblings to their .ts sources:

.
├── gen
│   └── lib
│       ├── schema.js
│       └── schema.ts
└── src
    ├── index.js
    ├── index.ts
    ├── lib
    │   ├── lib.js
    │   ├── lib.ts
    │   └── schema.graphql
    └── test
        ├── test.ts
        └── test.ts

This is very much not what I want or expect, and a big difference from the behavior of rootDir.

What I expect is that rootDirs acts like a multi-value rootDir, and for each input the root dir that it's in is stripped from the output path.

One additionally confusing aspect of rootDir vs rootDirs is that "rootDir": "./src" is not equivalent to "rootDirs": ["./src"]. The former will cause output files to be siblings to inputs.

It looks like to work around this we need to set "outDir": "./build", and then add an additional build step just to copy the files from ./build/src and ./build/gen into ./. This obviously can work but it's more of a complication than just a simple step: --watch will no longer work correctly unless you wire up the copy step to automatically run when ./build files change. For a project with simple build scripts, this is a pretty big leap in complexity.

Starting package.json:
  "scripts": {
    "build": "tsc --build"
  },
Desired addition of a generator:
  "scripts": {
    "build": "npm run build:graphql && npm run build:ts",
    "build:ts": "tsc --build",
    "build:graphql": "graphql-codegen"
  },
Actual addition of a generator, with broken --watch:
  "scripts": {
    "build": "npm run build:graphql && npm run build:ts && npm run build:copy",
    "build:ts": "tsc --build",
    "build:graphql": "graphql-codegen",
    "build:copy": "cp -r build/{src,gen}/*"
  },
Actual addition of a generator, with working --watch:

🤷‍♂️ I have to go figure this out still. Also, I'm not sure if this will badly interact with a monorepo, composite projects, and --build. The cross-package import paths are going to be different from the compiler output.

Potential workaround

I tried setting "rootDir": "./(src|gen)", hoping to tell tsc to strip those paths from the output. No luck as that path isn't interpreted as a pattern. That could potentially be a non-breaking way to add merging.

💻 Use Cases

Compiling generated files into a common output tree.

主要語言
Go
星號
111k
分支
14.4k
平均合併
1 天 19 小時
30 天內合併 PR
117

貢獻指南

開啟貢獻指南

從這裡開始

  1. 先讀完整個 Issue,再讀專案的貢獻指南。
  2. 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
  3. Fork 儲存庫,在一個分支上完成修改。
  4. 送出 Pull Request,並在描述裡引用這個 Issue 編號。

microsoft/TypeScript 的其他 Issue

查看 microsoft/TypeScript 的全部 Issue

相似的 Issue

更多 Go Issue

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。