microsoft / microsoft/TypeScript
tsconfig.json should support multiple configurations
Dieses Issue hat noch niemand übernommen.
- Vorherrschende Sprache
- Go
- Sterne
- 111k
- Forks
- 14.4k
- Ø Merge
- 1 T. 19 Std.
- Gemergte PRs (30 T.)
- 117
Beschreibung
Search Terms
multiple configurations, transitive closure
Suggestion
When using multiple packages in a monorepo, it is common to have a tsconfig.shared.json that all packages extend in their individual tsconfig.json. The current system makes it difficult to support various build configurations across packages (such as "dev" vs. "prod").
Because a property named "config" seems redundant in a file named tsconfig.json, I'll borrow the term select from Bazel and propose the following new option in a tsconfig.json file for defining configurations:
// tsconfig.shared.json
{
// Via "select", we define two configurations: "universal" and "modern".
"select": {
"universal": {
"compilerOptions": {
"target": "es3",
"downlevelIteration": true,
},
},
"modern": {
"compilerOptions": {
"target": "es2019",
},
},
},
// These compilerOptions are common to both configurations.
"compilerOptions": {
"sourceMap": true,
"module": "esnext",
"moduleResolution": "node",
"lib": ["dom", "es5", "es2019"],
"strict": true,
},
}
To complement this, tsc would have to support a new --select flag:
# Assume tsconfig.json extends tsconfig.json and defines "include" and "references".
# This would build the modern configuration.
$ tsc --build --select modern -p tsconfig.json
Ideally, it would also be possible to parameterize paths such as outDir so that you could also define this on the base compilerOptions in tsconfig.shared.json:
"outDir": "./dist/${select}/",
though I haven't been able to get "outDir" to do what I want in tsconfig.shared.json in my own project, so there might be more work to do on that front.
Use Cases
I want to be able to have a shared tsconfig.json that defines multiple configurations in one place that can be shared across multiple modules, as opposed to the current situation where we need O(M ⋅ C) tsconfig.json files where M is the number of modules and C is the number of configurations. A detailed example is below.
Examples
I have a Yarn workspace where each package is under the modules/ folder, so my root package.json contains the following:
{
"workspaces": [
"modules/*"
],
"scripts": {
"compile": "tsc --build modules/*"
}
}
I also have a shared.tsconfig.json in the root of my Yarn workspace where I define the "compilerOptions" that I want all packages in the workspace to use. (For example, I set "target": "es2019" in shared.tsconfig.json.) Each folder under modules/ contains its own tsconfig.json file that contains the line:
"extends": "../../tsconfig.shared.json",
and there is also a "references" property with the appropriate list of relative paths to other packages in the workspace.
Ideally, each such tsconfig.json would contain only "extends" and "references", but it seems I have to redeclare "compilerOptions.outDir" and "include" in each of these files even though the values are the same in each one (["src/**/*"] and "./dist", respectively).
OK, so far, so good, but now I want to be able to build my entire Yarn workspace with a different set of compilerOptions, specifically:
"downlevelIteration": true,
"target": "es3",
Ideally, I would be able to specify this in one place and leverage the "references" I already had to define so I could compile one .ts file or package and all of its transitive deps with these compiler options. (I happen to be using ts-loader in Webpack, so my ultimate output is a single .js file, which perhaps biases my expectations here.)
Unfortunately, there does not appear to be any clean way to do that. I could go through and define a tsconfig.es3.json in each of my packages that looks like this:
{
"extends": "./tsconfig.json",
"compilerOptions": {
"downlevelIteration": true,
"target": "es3",
},
}
though even if I did that, I'm not sure I could build all of my modules as ES3 with a one-liner as I did in my original package.json file. Now I'm faced with the additional incidental complexity of:
- Maintaining O(M)
tsconfig.es3.jsonfiles and ensuring all of them are in sync. - Introducing Lerna or some other tool to "walk my DAG" and run
tsc -b -p tsconfig.es3.jsonor something like that.
With the --select proposal, I could avoid the extra tsconfig.json files and still build via a one-liner:
tsc --build --select universal modules/*
I would expect if any of the tsconfig.json files under modules/* did not define a "universal" configuration, the build command would fail (or at least the strictness should be configurable).
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, etc.)
- This feature would agree with the rest of TypeScript's Design Goals.
Beitragsleitfaden
Erste Schritte
- Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
- Forke das Repository und arbeite in einem Branch.
- Öffne einen Pull Request, der die Issue-Nummer nennt.
Rechercherichtung
Beginne mit der in der Issue beschriebenen Vererbung von tsconfig.json und den Projektverweisen und verfolge dann den Einstiegspunkt von tsc --build. Vergleiche die vorgeschlagenen Auswahlkonfigurationen und das Flag --select mit dem bestehenden Build-Verhalten; als erledigt gilt die Auswahl einer gemeinsamen Konfiguration über die referenzierten Pakete hinweg, mit einer eindeutigen Behandlung fehlender Auswahlen und jeglicher Parametrisierung von Pfaden.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Bewertung
- Tech-Stack
- typescript
- Bereich
- build-system
- Issue-Typ
- Feature
- Schwierigkeit
- 5/5
- Geschätzter Aufwand
- Über eine Woche
- Aktivitätsstatus
- Veraltet
- Klarheit
- Klar beschrieben
- Anfängerfreundlichkeit
- 25/100