TypeScript with Node.js

TypeScript has had first class support for Node.js since inception. Here's how to setup a quick Node.js project:

Note: many of these steps are actually just common practice Node.js setup steps

  1. Setup a Node.js project package.json. Quick one : npm init -y
  2. Add TypeScript (npm install typescript --save-dev)
  3. Add node.d.ts (npm install @types/node --save-dev)
  4. Init a tsconfig.json for TypeScript options with a few key options in your tsconfig.json (npx tsc --init --rootDir src --outDir lib --esModuleInterop --resolveJsonModule --lib es6,dom --module commonjs)

That's it! Fire up your IDE (e.g. code .) and play around. Now you can use all the built in node modules (e.g. import * as fs from 'fs';) with all the safety and developer ergonomics of TypeScript!

All your TypeScript code goes in src and the generated JavaScript goes in lib.

Bonus: Live compile + run

  • Add ts-node which we will use for live compile + run in node (npm install ts-node --save-dev)
  • Add nodemon which will invoke ts-node whenever a file is changed (npm install nodemon --save-dev)

Now just add a script target to your package.json based on your application entry e.g. assuming its index.ts:

  "scripts": {
    "start": "npm run build:live",
    "build": "tsc -p .",
    "build:live": "nodemon --watch 'src/**/*.ts' --exec 'ts-node' src/index.ts"

So you can now run npm start and as you edit index.ts:

  • nodemon reruns its command (ts-node)
  • ts-node transpiles automatically picking up tsconfig.json and the installed TypeScript version,
  • ts-node runs the output JavaScript through Node.js.

And when you are ready to deploy your JavaScript application run npm run build.

Creating TypeScript node modules

Using modules written in TypeScript is super fun as you get great compile time safety and autocomplete (essentially executable documentation).

Creating a high quality TypeScript module is simple. Assume the following desired folder structure for your package:

├─ package.json
├─ tsconfig.json
├─ src
│  ├─ All your source files
│  ├─ index.ts
│  ├─ foo.ts
│  └─ ...
└─ lib
  ├─ All your compiled files
  ├─ index.d.ts
  ├─ index.js
  ├─ foo.d.ts
  ├─ foo.js
  └─ ...
  • In your tsconfig.json

    • have compilerOptions: "outDir": "lib" and "declaration": true < This generates declaration and js files in the lib folder
    • have include: ["./src/**/*"] < This includes all the files from the src dir.
  • In your package.json have

    • "main": "lib/index" < This tells Node.js to load lib/index.js
    • "types": "lib/index" < This tells TypeScript to load lib/index.d.ts

Example package:

  • npm install typestyle for TypeStyle
  • Usage: import { style } from 'typestyle'; will be completely type safe.


  • If your package depends on other TypeScript authored packages, put them in dependencies/devDependencies/peerDependencies just like you would with raw JS packages.
  • If your package depends on other JavaScript authored packages and you want to use it with type safety in your project, put their types (e.g. @types/foo) in devDependencies. JavaScript types should be managed out of bound from the main NPM streams. The JavaScript ecosystem breaks types without semantic versioning too commonly, so if your users need types for these they should install the @types/foo version that works for them.

Bonus points

Such NPM modules work just fine with browserify (using tsify) or webpack (using ts-loader).

results matching ""

    No results matching ""