Why you should have 3 tsconfig.json files
Published:
Heads up! This content is more than six months old. Take some time to verify everything still works as expected.
I've been working on a couple type of code bases in Typescript for our company
that use direct
tsconfig.json
files instead of inherited
versions. I noticed a off and on but never really let it bug me that the behavior of
test.ts
/ spec.ts
(Jest),
or stories.tsx
(Storybook)
was always different than our src
code.
I recall one time starting to investigate
by trying to change the exclude
settings
as I knew we were ignoring those types of files via patterns. Just including those files
back into considering broke our builds though, as we changed the actual build output from
just the content of src
published to dist
or lib
. Instead, with the exclusions removed
the build directories now included their own src
and test
folders. No good. With
too little time available to really dig into the issue, I dropped it. After all,
the thing compiled; it was a very minor syntax issue or ignore note in just non-production
files.
Recent work on a starting a Lerna monorepo that will offer our clients Typescript SDK's via NPM packages forced me to confront the issue more head on. That breakdown, of fighting to get NPM, TS, and Jest to all play nice is a much larger battle still ongoing. I'll post it once I get it all working.
One small tidbit I do want to pull out separately though is the concept of multiple
tsconfig.json
. Each package in the monorepo required its own as the
rootDir
changed.
This meant either a full copy paste (ick) or using
extends
. Obviously, I choose
to inherit all the possible configurations I could from the root tsconfig.json
.
In doing this I noticed that the includes
and excludes
were wrong of course.
This lead me to the idea of keeping a root tsconfig.base.json
version with the
compilerOptions
just as they suggest in the docs for extends
. Each package then had
its own tsconfig.build.json
and I just updated the build
commands to use the
-p ./tsconfig.build.json
argument where I could use exclude
for spec, test, and story
files. Great! One last problem though, the IDE has no idea what my options are. There lies
your last tsconfig.json
file, the one that used to be my default in the project root.
It's nothing more than a extends
in most cases, but it makes IDE's and allows little tweaks.
As example, here's my current 3 usages for an API project:
tsconfig.base.json
{ "compilerOptions": { "allowJs": true, "allowSyntheticDefaultImports": true, "declaration": true, "declarationDir": "./lib", "outDir": "./lib", "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "jsx": "react", "isolatedModules": false, "lib": ["dom", "dom.iterable", "esnext"], "module": "esnext", "moduleResolution": "node", "resolveJsonModule": true, "skipLibCheck": true, "strict": true, "target": "es5" } }
tsconfig.json
{ "extends": "./tsconfig.base.json", "include": [".storybook", "src", "stories"], "exclude": ["node_modules"] }
tsconfig.build.json
{ "extends": "./tsconfig.base.json", "include": ["src"], "exclude": ["node_modules", "**/*.test.*", "**/*.stories.*"] }