mkdir ts-library
cd ts-library
pnpm init
pnpm add -D typescript tsup @types/node
touch tsconfig.json
touch tsup.config.ts
mkdir src
touch src/index.ts
touch .gitignore
touch README.md
typescript → compilertsup → bundler (esbuild-based, very fast)@types/node → Node typespackage.json{
"name": "atari-monk-ts-library",
"version": "0.0.1",
"description": "Minimal TypeScript library template",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"require": "./dist/index.cjs"
}
},
"files": [
"dist"
],
"scripts": {
"build": "tsup",
"dev": "tsup --watch",
"clean": "rm -rf dist"
},
"keywords": [],
"license": "MIT"
}
Key points:
exports field (modern npm best practice)dist/tsconfig.json
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "Bundler",
"declaration": true,
"strict": true,
"skipLibCheck": true,
"outDir": "dist",
"noEmit": true
},
"include": ["src"]
}
Why noEmit: true?
tsup.config.ts
import { defineConfig } from "tsup";
export default defineConfig({
entry: ["src/index.ts"],
format: ["esm", "cjs"],
dts: true,
clean: true,
sourcemap: true,
outDir: "dist",
minify: false
});
This ensures:
hello functionsrc/index.ts
export function hello(name: string): string {
return `Hello, ${name}!`;
}
.gitignorenode_modules
dist
# ts-library
Minimal TypeScript library template.
## Install
pnpm add ts-library
### Usage
```ts
import { hello } from "ts-library";
console.log(hello("world"));
```