Skip to content

Instantly share code, notes, and snippets.

@gustavopch
Created May 17, 2020 14:54
Show Gist options
  • Save gustavopch/a4b9d4b0d07de98b795f023a1a96ebce to your computer and use it in GitHub Desktop.
Save gustavopch/a4b9d4b0d07de98b795f023a1a96ebce to your computer and use it in GitHub Desktop.
TypeScript with project references and incremental build in a monorepo

So, in summary, we have:

packages/
  app/
    tsconfig.json
  shared/
    tsconfig.json
tsconfig.base.json
tsconfig.json

Running tsc -b --incremental from the root will read the root tsconfig.json file which references the packages/app/tsconfig.json file which in turn references the packages/shared/tsconfig.json file.

// File: ./packages/app/tsconfig.json
// This is the config for the app package.
// Note: same notes on relative paths written in the file above apply
// here. Yes, it seems repetitive to declare the same paths again, but
// it's necessary.
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"baseUrl": "./src",
"declarationDir": "./types",
"rootDir": "./src",
"typeRoots": [
"./@types",
"./node_modules/@types",
"../../@types",
"../../node_modules/@types"
]
},
"include": ["./src"],
// Here we reference the shared package.
"references": [{ "path": "../shared" }]
}
// File: ./tsconfig.base.json
// This is the base config that will be extended by all other ones.
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
// In order to make packages referenceable by others, they
// must have 'composite' enabled.
"composite": true,
// We're only interested in type checking. Transpiling '.ts'
// files to '.js' will be done by Create React App.
"emitDeclarationOnly": true,
"esModuleInterop": true,
"isolatedModules": true,
"jsx": "preserve",
"lib": ["dom", "dom.iterable", "esnext"],
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"skipLibCheck": true,
"strict": true,
"target": "es5"
},
"exclude": ["**/node_modules"]
}
// File: ./packages/shared/tsconfig.json
// This is the config for the shared package.
// Note: paths are always relative to the current config file, so
// specifying the paths in the base config wouldn't work well, thus we
// need to specify them inside each 'packages/*'.
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"baseUrl": "./src",
// As said before, we're not interested in actually transpiling but
// just type-checking, so we use 'declarationDir' here pointing to
// a place different from './build' so that declaration files emitted
// by 'tsc' are separated from the resulting Create React App build.
"declarationDir": "./types",
"rootDir": "./src",
"typeRoots": [
"./@types",
"./node_modules/@types",
"../../@types",
"../../node_modules/@types"
]
},
"include": ["./src"]
// Note there's no 'references' field here as this package don't really
// import any other internal package from our monorepo.
}
// File: ./tsconfig.json
// This is the 'solution config' which will be used as the entry point when
// running 'tsc -b --incremental'.
{
// Important to declare 'files' as an empty array as this file won't be
// responsible for building or type-checking anything. It's just referencing
// the actual configs of each package.
"files": [],
"references": [
// When we run 'tsc -b --incremental', TypeScript will look for each
// package referenced here in order to build (or type-check) them. Think
// of this as the entry points - each referenced package will be able to
// reference other ones - so we don't need to list everything here.
{ "path": "./packages/app" }
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment