microsoft / microsoft/TypeScript
Compiler option to define output-to-input directory map for module resolution of package.json `"imports"`/`"exports"`
- 主要言語
- Go
- スター
- 111k
- フォーク
- 14.3k
- 平均マージ
- 2日 4時間
- マージ済み PR(30日)
- 132
説明
### 🔍 Search Terms
"rootDir", "outDir", "paths", "map", "mapping", "imports", "exports", "moduleResolution", "module resolution"
### ✅ Viability Checklist
- [x] This wouldn't be a breaking change in existing TypeScript/JavaScript code
- [x] This wouldn't change the runtime behavior of existing JavaScript code
- [x] This could be implemented without emitting different JS based on the types of the expressions
- [x] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
- [x] This isn't a request to add a new utility type: https://github.com/microsoft/TypeScript/wiki/No-New-Utility-Types
- [x] This feature would agree with the rest of our Design Goals: https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals
### ⭐ Suggestion
A TS project with `moduleResolution: bundler` (and others) uses the `rootDir` and `outDir` options to map the project's package.json `"imports"` and `"exports"` entries from `outDir` to `rootDir` directory. However, this only works for files inside `rootDir`.
A new option could be introduced for programs to define/inform that another local project compiles `rootDir` into `outDir`. This would be similar (indeed, identical in intent) to the `paths` option, but with more convenient support for package.json's `"imports"`/`"exports"` resolution, since only output-to-input directory mappings are required; with `paths`, one mapping would be required for every `"imports"` and `"exports"` entry.
### 📃 Motivating Example
Consider a project with the following structure:
```
├──📁 src
├──📁 test
├──📄 package.json
├──📄 tsconfig.json // references the other config files
├──📄 tsconfig.src.json
└──📄 tsconfig.test.json
```
```jsonc
// tsconfig.src.json
"compilerOptions": {
"module": "esnext",
"moduleResolution": "bundler",
"rootDir": "src",
"outDir": "dts",
},
"include": ["src"]
```
```jsonc
// package.json
"imports": {
"#foo": {
"types": "./dts/foo.d.ts"
}
}
```
With the previous configuration, tsc is able to resolve `#foo` imports inside `src/`, even if `dts/` has not yet been generated, because of `rootDir` and `outDir`.
The desired behavior is for `tsconfig.test.json` (for the `test/` directory) to also be able to resolve `#foo` imports before `dts/` is generated. That is, inform `tsconfig.test.json` that other program compiles `src` into `dts`. This could be achieved with a new compiler option:
```ts
// tsconfig.test.json
"": {
"dts": "src" // Inform tsc that other program compiles src into dts
}
```
### 💻 Use Cases
To resolve package.json's `"imports"` and `"exports"` output file paths by mapping them to corresponding input files. It may be seen in the previous example that this would be useful in the same way import specifier maps with `paths` is useful, but more convenient for `"imports"`/`"exports"` resolution.
### Alternatives
#### 1. `paths`
The desired behavior can be achieved with the `paths` option, but it is not as convenient since a map entry is required for every `"imports"` and `"exports"` entry, `paths` mappings are in a different file, and updating `"imports"`/`"exports"` requires a corresponding `paths` update.
```jsonc
// package.json
"imports": {
"#foo": {
"types": "./dts/foo.d.ts"
},
"#bar": {
"types": "./dts/bar.d.ts"
}
}
```
```jsonc
// tsconfig.json
"paths": {
"#foo": ["./src/foo.ts"],
"#bar": ["./src/bar.ts"]
}
```
Besides, it seems more appropriate for tsc to resolve "#" and self-reference import specifiers from paths defined by package.json `"imports"`/`"exports"` since that is, after all, their purpose.
#### 2. `customConditions`
A second alternative is using `customConditions`, but drawbacks are somewhat similar. Although with a custom condition, all map entries can be defined in package.json, more boilerplate is required:
```jsonc
// package.json
"imports": {
"#foo": {
"types": {
"dev": "./src/foo.ts",
"default": "./dts/foo.d.ts"
}
},
"#bar": {
"types": {
"dev": "./src/bar.ts",
"default": "./dts/bar.d.ts"
}
}
}
```
```jsonc
// tsconfig.json
"customConditions": ["dev"]
```
This, however, better mirrors the desired behavior; the resolution process with this configuration is very similar to the `outDir` to `rootDir` mapping tsc performs (see [package.json "imports" and self-name imports](https://www.typescriptlang.org/docs/handbook/modules/reference.html#packagejson-imports-and-self-name-imports)).
コントリビューションガイド
調査の方向性
この issue では、リポジトリのソースファイルやテストが指定されていません。まず、示されている tsconfig.src.json と tsconfig.test.json の設定で、rootDir/outDir および package.json の "imports" と "exports" の動作を再現し、その後、既存の moduleResolution の処理を追跡してください。文書化された compiler option によって、別のプロジェクトの出力ディレクトリを対応する入力ファイルへ戻してマッピングでき、対応する paths エントリを要求しない状態になれば完了です。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- typescript
- 領域
- compilers
- issue の種類
- 機能追加
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 活発さ
- 停滞
- 明瞭さ
- おおむね明確
- 初心者へのやさしさ
- 28/100