-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal for enhancing ways to extend tsconfig file #56436
Comments
I would definitely like to see more powerful options like these here. A few thoughts: For {
"extends": "./tsconfig.base.json",
"compilerOptions": {
// Override:
"paths": {
"@libs/*": ["libs/*"],
"@project1/*": ["project1/*"]
},
// Merge:
"extend": {
"paths": {
"@libs/*": ["libs/*"],
"@project1/*": ["project1/*"]
}
}
}
} I think the semantics can be the same as what you proposed, but (a) this scheme has prior art that will be familiar to many, and (b) the indicator that an extension is happening is more closely colocated with the property doing the extending. Instead of // tsconfig.base.json
{
"compilerOptions": {
"outDir": "${projectRoot}/dist"
}
} This is again just different syntax for the same semantics you proposed, but I like it because (a) itβs obvious whatβs intended to happen just by looking at the option value, (b) itβs impossible to forget whether |
For For |
I find the desire to extend {
"compilerOptions": {
"extend": {
"paths": {
"@/foo/*": ["../packages/foo/dist/*"]
}
}
},
"extend": {
"references": [
{ "path": "../packages/foo" }
]
}
} Overall, I think clarity should be the top priorityβitβs hard to imagine config parsing being a significant part of the total compilation time of a large app. |
we probably need to use "merge" instead of "extend" given we already have "extends" at root |
Writing The original The raw option, as described, also seems fantastic. It gives projects control over paths and allows them to keep standards easily. Regarding Making the merge too configurable seems too much. A simple object merge and array concat seem reasonable and beautifully address most users' requests. Thanks a lot for bringing that to light, @sheetalkamat; I hope other users engage in this discussion. |
+1 A very useful and necessary feature, especially in monorepositories (as in my case) |
Coincidentally, we are developing a system that requires processing of this kind of configs with a declarative extras ( const tsconfig = await populate('tsconfig.json', {
rules: {
compilerOptions: 'merge',
'compilerOptions.paths': 'merge',
'compilerOptions.typeRoots': 'merge'
},
vmap({value, cwd, root, prefix, key}) {
if (cwd !== root && (
prefix === 'compilerOptions.outDir' ||
prefix.startsWith('compilerOptions.typeRoots.') ||
/^compilerOptions\.paths\.[^.]+\./.test(prefix))
) {
return path.join(path.relative(root, cwd), value)
}
return value
}
}) It's definitely too verbose. So const tsconfig = await populate('tsconfig.json', {
compilerOptions: 'merge',
'compilerOptions.paths': 'merge',
'compilerOptions.typeRoots': 'merge',
'compilerOptions.typeRoots.*': 'rebase',
'compilerOptions.outDir': 'rebase',
'compilerOptions.paths.*.*': 'rebase'
}) |
π Search Terms
"extends", "merge", "compilerOptions", "paths", "outdir", "include", "exclude", "typeRoots", "references", "tsconfig", "ability to merge tsconfig", "ability to make tsconfig paths relative to final config"
β Viability Checklist
β Suggestion
Today when you extend a config the options written in the final config override the options from the base config. Here is sample of what happens today:
Here is what it would mean that project1 tsconfig was written as:
Over years users have asked us for ability to create a final config that adds to base config instead of overriding. This is extremely useful for
paths
from compiler options or sayreferences
that specify project references.This would allow to users to write a base config that contains common options that shouldn't have to be copied in all projects and yet allowing projects to specify there additional specific options.
For example in above sample, one would expect a way to write config such that final
paths
property is:Here is the proposal to add
merge
as root level config property that specifies options that need to merged instead of completely overwritten in the final config.The values specified in merge can be root level properties:
files
,include
,exclude
andreferences
or option names from eithercompilerOptions
,watchOptions
ortypeAcquisition
which are lists or object type eg.paths
,typeRoots
,libs
etc.From the above example writing the
project1
config as:per @andrewbranch 's suggestion here: #56436 (comment)
other option is to write config as:
Would mean that project1 wrote the tsconfig as:
Note how the paths still remain relative to config they are defined in but allowing one to add more properties and if say baseConfig also had rule for
@environment/*
path mapping it is overwritten by the project1 specific. That is it does not recusively merge property values of path mappings.Apart from having ability to specify specific options that get merged, users have often asked us for a way to specify config such that base config will specify option say
outDir
and instead of it being relative to the base config, it needs to be relative to project's tsconfig.For example in the above example, instead of all projects output going into
/temp/test/dist
the output to be inside eachdist
folder of each project.Apart from
outDir
this would also help in writing base configs such that extendingbase.tsconfig.json
would include project'ssrc
files and extendingbase.test.tsconfig.json
would includetests
filesWith below configs:
Today the resulting config of project1 is:
Proposal here is to add property
raw
with names of properties in base config such that extending it would mean as if project extending it specified them, making them relative to final config instead of the base config.So with change to base.tsconfig.json as:
per @andrewbranch suggestion option 2 to consider:
would result in final project1 config as if it wrote:
and another project2 say with
merge
property as:would result in configuration as if written as:
The property
raw
can be used for:outDir
,declarationDir
etcrootDirs
,typeRoots
fromcompilerOptions
orexcludeFiles
,excludeDirectories
fromwatchOptions
include
andexclude
root config properties. (files
andreferences
are not included here as not sure if they really make sense?)paths
is a special option where normally the base path (propertypathsBasePath
) is relative to config they are declared in. So addingpaths
toraw
would mean that path mapping is done relative to config file extending the root config file.There was consideration of specifying
raw
extend as part of config extending root config but that would mean either writing something like"rawExtend": ["outDir", "typeRoots"]
or"merge": [{ "name": "include", "kind": "raw" }]
in each config defeating the purpose of concise extend. Any feedback on that?Should
merge
be in root config: probably not because if project wants to override or add should be part of project decision and it would need to add properties to list only if that config specifies to making this property of project config makes more sense.TODO:
What happens to
raw
andmerge
when multi-level extending is in play. Probably they need to be merged instead of overwritten but need to think about that.Here are issues this would help with:
#44589
#27098
#20110
#29172
π Motivating Example
A way to specify say project specific "paths" mapping without having to rewrite all the mappings from the base config.
And a way to specify root config that can specify
include
and/oroutDir
and not needing to write than in each project.π» Use Cases
The text was updated successfully, but these errors were encountered: