Strategies for live-updating TypeScript types in monorepos
https://github.com/colinhacks/live-typescript-monorepo.git
Read the associated blog post for complete information.
In development, your TypeScript code should feel "alive". When you update your code in one file, the effects of that change should propogate to all files that import it.
This is true even for monorepos, where you may not be importing things from a file, but from a local package.
- import { Fish } from "../pkg-a/index";
+ import { Fish } from "pkg-a"
This repo contains a few strategies you can use to make your TypeScript monorepo feel more alive.
Each subdirectory contains a pnpm monorepo (pnpm-workspace.yaml) with two packages, pkg-a and pkg-b. pkg-b has a dependency on pkg-a. Each package has a tsconfig.json that extends a tsconfig.base.json in the root of the monorepo.
The file structure looks something like this:
.
โโโ package.json
โโโ packages
โย ย โโโ pkg-a
โย ย โย ย โโโ index.ts
โย ย โย ย โโโ package.json
โย ย โย ย โโโ tsconfig.json
โย ย โโโ pkg-b
โย ย โโโ index.ts
โย ย โโโ package.json
โย ย โโโ tsconfig.json
โโโ pnpm-lock.yaml
โโโ pnpm-workspace.yaml
โโโ tsconfig.base.json
โโโ tsconfig.json
Let's break down the approaches. (Refer to the associated blog post for complete breakdowns.)
1. project-referencesUse TypeScript project references to link packages together. This has a lot of downsides and doesn't play nice with node or other tooling out of the box.
2. publishConfigUse publishConfig in package.json to specify .ts file in development and .js file in production.
3. tsconfig-pathsConfigure compilerOptions.paths in tsconfig.json to override resolution for local package names.
4. tshy-devUsing tshy's liveDev mode to hard-link the .ts source code directly into ./dist/esm and ./dist/commonjs directories. This lets VS Code discover your live TypeScript source code without any additional package.json configuration.
5. custom-conditionsRecommended User-defined conditional export in package.json#exports plus customConditions in tsconfig.json
To play around with a particular approach, clone this repo and navigate to the appropriate subdirectory.
$ gh repo clone colinhacks/live-typescript-monorepo
$ cd live-typescript-monorepo
$ cd <subdir> # tsconfig-paths, publishconfig, project-references, custom-conditions
Then run the following commands:
$ pnpm i # install
$ code . # open in VS Code
Once the project is open in VS Code, open packages/pkg-a/index.ts and packages/pkg-b/index.ts. When you change the definition of Fish in pkg-a, those changes should propagate immediately to pkg-b without a build step.
Each subdirectory also contains a "test" script that executes pkg-b/index.ts. (This won't work in project-references.) This should execute the latest .ts files for both pkg-a and pkg-b! Make some changes and see the effects.
pnpm test
Happy monorepo hacking!