Shipping type declarations with your TS library is not enough

One of the greatest benefits of building libraries with TypeScript is the ability to auto-generate and ship type declarations alongside your code for the consumers to use. This greatly enhances the developer experience, but there is still some room for improvement.

If your library is open-source or if it is internal and thus only used inside your org, I suggest you to additionally ship full source code, source and declaration maps. Even if your product is closed-source but it is developed in a multi-project workspace, all of my suggestions still apply.

Of course, this has some cons (namely, bloated packages, though the extent of this “bloating” is questionable), but IMO the advantages greatly outweigh the disadvantages. Let’s take a look at some examples.

Example #1. io-ts (v2.2.16)

io-ts is (unsurprisingly) built with TS and it ships type declarations alongside the built code. However, whenever you want to take a closer look at the library’s internals and navigate to some imported entity (Ctrl+Click) you end up in a type declaration file:

io-ts

To see the actual source code you need to:

  1. Find out the version of io-ts you are using.
  2. Find the source code of the specific version of the library (hopefully the developers tagged the release!).
  3. Find the file you are interested in.
  4. Find the entity in the file.

Is there a better way? Yes, declaration maps can help.

Example #2. @dkamyshov/sample-library (v0.0.3)

This is a sample library I built for illustration purposes. Install it and import the sum function. Then Ctrl+Click it and viola! You will jump straight to the source code:

@dkamyshov/sample-library

There are many ways to enable the generation of declaration maps depending on your tooling. In general it is enabled by adding "declarationMap": true to tsconfig.json.

Why include source maps?

The benefit of including source maps in addition to the source code is the ability for consumers to debug your library in-place. These source maps can be consumed by something like source-map-loader (if you use webpack), included in your project’s source maps and then again consumed by the debugger (built-in browser debugger or any standalone debugger that supports source maps, you might need to adjust source map paths, though).