TypeScript

Publishing Your TypeScript Package to npm: A Step-by-Step Guide

Publishing a TypeScript package to npm is one of those things that sounds simple until you hit the first "module not found" error from a consumer. Getting...

14 Apr 2024

Publishing Your TypeScript Package to npm: A Step-by-Step Guide

Publishing a TypeScript package to npm is one of those things that sounds simple until you hit the first "module not found" error from a consumer. Getting the build output, type declarations, and module formats right takes a few deliberate steps.

Here's how I do it.

Step 1: Initialize the package

Bash
npm init

Fill in the name, version, and description. Nothing fancy.

Step 2: Set up Git

Bash
git init

Point the remote at GitHub or wherever you host.

Step 3: Configure package.json

This is where most people get tripped up. You need to tell npm where the built files live and what formats you support:

Json
{
  "type": "module",
  "main": "./dist/index.js",
  "module": "./dist/index.mjs",
  "types": "./dist/index.d.ts",
  "files": ["dist"]
}

main is for CommonJS consumers. module is for ESM. types points to your type declarations. files ensures only the dist folder gets published — not your source, not your tests.

Step 4: Set up tsup

I use tsup for building. It handles dual CJS/ESM output and declaration files with minimal config.

Bash
npm install tsup --save-dev

Create a tsup.config.ts:

Typescript
import { defineConfig } from "tsup";

export default defineConfig({
  entry: ["src/index.ts"],
  format: ["cjs", "esm"],
  dts: true,
  clean: true,
});

Step 5: Publish

Bash
npm publish

The trade-off

tsup makes the build trivial. The cost: it's another dependency, and if you need fine-grained control over the output, you'll eventually outgrow it and reach for raw tsc + bundler config.

For most packages, tsup is the right call. Ship it, move on.

Keep reading