Building and Publishing TypeScript Libraries to npm

Table of Contents

  • Why Publish a TypeScript Library?
  • Key Considerations Before Publishing
  • Setting Up Your Library Project
  • Configuring tsconfig.json for Libraries
  • Writing TypeScript Code
  • Bundling Your Library
  • Preparing package.json
  • Managing .npmignore or files field
  • Building the Library
  • Publishing to npm
  • Versioning and Publishing Best Practices
  • Conclusion

Why Publish a TypeScript Library?

Publishing your own TypeScript library allows you to:

  • Share reusable code (e.g., UI components, utilities, SDKs).
  • Establish credibility as an open-source contributor or expert.
  • Empower your team internally or support the larger developer community.

A properly published TypeScript library ensures:

  • Consumers get typed support out of the box.
  • Both JavaScript and TypeScript projects can easily consume it.

Key Considerations Before Publishing

  • Type Definitions: Ensure your .d.ts files are available.
  • Build Output: Ship clean, compiled JavaScript.
  • Bundling: Use tools like tsup, rollup, esbuild if necessary.
  • ESModules vs CommonJS: Decide the module target.
  • Tree Shaking: Export ES modules for better optimization.
  • License and Readme: Add a LICENSE and README.md.

Setting Up Your Library Project

Create a new folder for your library:

mkdir my-awesome-lib
cd my-awesome-lib
npm init -y

Install development dependencies:

npm install --save-dev typescript

Optionally, you may add bundlers like tsup, rollup, or vite later if needed.

Project structure:

my-awesome-lib/
├── src/
│ └── index.ts
├── package.json
├── tsconfig.json
├── README.md
└── LICENSE

Configuring tsconfig.json for Libraries

Here’s a minimal tsconfig.json for building a library:

{
"compilerOptions": {
"target": "ES2019",
"module": "ESNext",
"declaration": true,
"declarationMap": true,
"outDir": "dist",
"rootDir": "src",
"moduleResolution": "Node",
"esModuleInterop": true,
"strict": true,
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}

Key options:

  • declaration: generates .d.ts files.
  • outDir: where to put the build output.
  • strict: ensures strong typing.

Writing TypeScript Code

Inside src/index.ts:

export function greet(name: string): string {
return `Hello, ${name}!`;
}

You can structure your library better if needed (e.g., create folders like utils, components, etc.).


Bundling Your Library (Optional but Recommended)

Instead of just using tsc, you can bundle using tsup, rollup, or esbuild.

Example with tsup:

Install tsup:

npm install --save-dev tsup

Add a build script in your package.json:

{
"scripts": {
"build": "tsup src/index.ts --format esm,cjs --dts"
}
}

This command will:

  • Create ESM and CommonJS outputs.
  • Generate .d.ts types automatically.

Tsup is fast and perfect for most libraries.


Preparing package.json

Update your package.json carefully:

{
"name": "my-awesome-lib",
"version": "1.0.0",
"description": "An awesome TypeScript library",
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"build": "tsc"
},
"repository": {
"type": "git",
"url": "https://github.com/yourusername/my-awesome-lib.git"
},
"keywords": [
"typescript",
"library"
],
"author": "Your Name",
"license": "MIT"
}

Important Fields:

  • main: CommonJS entry.
  • module: ESModule entry (for modern bundlers).
  • types: Points to the TypeScript declarations.
  • files: Only publish necessary files (like dist/).

Managing .npmignore or files Field

Instead of .npmignore, it’s better to use the files field in package.json.

If you still prefer .npmignore, make sure you exclude:

  • /src
  • /node_modules
  • /tests
  • /example
  • /scripts

Example .npmignore:

src/
node_modules/
tests/
example/
scripts/
tsconfig.json

Building the Library

Run the build:

npm run build

It will generate:

  • JavaScript files (.js or .mjs)
  • Type definition files (.d.ts) inside the dist/ folder.

Publishing to npm

  1. Login to npm:
npm login
  1. Publish:
npm publish --access public
If your package name is scoped (e.g., @your-org/my-lib), you must use --access public to make it public.
  1. Done! Your library is live!

Versioning and Publishing Best Practices

  • Follow Semantic Versioning (semver):
    • MAJOR.MINOR.PATCH
    • Major = breaking changes
    • Minor = new features (no breaking)
    • Patch = fixes
  • Add proper CHANGELOG.md.
  • Use GitHub Releases or npm Release Notes.
  • Tag your Git commits (git tag v1.0.0).
  • Set up CI/CD to auto-publish on pushes (e.g., GitHub Actions).

Conclusion

Publishing a TypeScript library to npm the right way ensures:

  • Developers get a clean and typed experience.
  • Your code is reliable and future-proof.
  • You and your brand build credibility in the community.

Quick Summary Workflow:

Code âž” Build âž” Publish âž” Repeat (with proper versioning)