How to Seamlessly Migrate a Node.js Project to TypeScript: Step‑by‑Step Guide

This article walks you through converting an existing Node.js codebase to TypeScript, covering directory restructuring, TypeScript and ESLint setup, handling common import and type errors, configuring debugging in VSCode, and gradually strengthening type safety while preserving project functionality.

WecTeam
WecTeam
WecTeam
How to Seamlessly Migrate a Node.js Project to TypeScript: Step‑by‑Step Guide

Introduction

If you have a Node.js project and want to refactor it with TypeScript, this guide will help you. It skips the basics of why TypeScript is popular and focuses on practical steps: directory layout, TypeScript‑ESLint configuration, tsconfig settings, debugging, and common error handling.

Step 1 – Adjust Directory Structure

Because TypeScript needs compilation, separate a src folder for source files and a dist folder for compiled output. A typical layout is:

|-- assets            # images, videos, etc.
|-- bin               # CLI entry, e.g., #!/usr/bin/env node
|-- dist              # compiled files (main points to package.json)
|-- docs              # documentation
|-- scripts           # script files referenced in package.json
|-- src               # only .ts files; other assets go to templates
|-- sub               # sub‑directories
|   └── ...
|-- cli.ts            # CLI entry file
|-- index.ts          # API entry file
|-- templates         # json, html, etc.
|-- tests             # test files
|-- typings           # custom .d.ts files for missing declarations
|-- .eslintignore
|-- .eslintrc.js
|-- .gitignore
|-- package.json
|-- README.md
|-- tsconfig.json

Step 2 – Install and Initialise TypeScript

Run the following commands in the project root:

npm i typescript -D          # install as a dev dependency
node ./node_modules/.bin/tsc --init   # generate tsconfig.json
# or, if TypeScript is installed globally:
# tsc --init

The generated tsconfig.json can be customised; a recommended baseline is provided later.

Step 3 – Adjust Source Files

Rename .js to .ts

Rename all JavaScript files to .ts and move them into src. Tools like gulp can automate this.

Extract Template Files

Files that are not compiled by TypeScript (e.g., .json, .html) should be placed in the templates directory.

Update package.json scripts

{
  "scripts": {
    "build": "tsc",
    "watch": "tsc --watch"
  }
}

Now npm run build or npm run watch compiles the project.

Step 4 – TypeScript Code Standards

Install ESLint for TypeScript:

npm i eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin -D

Create .eslintrc.js with a minimal configuration:

module.exports = {
  parser: '@typescript-eslint/parser',
  extends: ['plugin:@typescript-eslint/recommended'],
  env: { node: true }
};

Optionally extend the standard rule set:

npm i eslint-config-standard eslint-plugin-import eslint-plugin-node eslint-plugin-promise eslint-plugin-standard -D
module.exports = {
  parser: '@typescript-eslint/parser',
  extends: ['standard', 'plugin:@typescript-eslint/recommended'],
  env: { node: true }
};

Integrate ESLint into VSCode for on‑save fixing and real‑time hints.

Step 5 – Resolve Common Errors

Missing Node.js declarations

Install @types/node:

npm i @types/node -D

Import syntax issues

Depending on the module system, use one of the following import styles (with esModuleInterop enabled):

import * as mod from 'mod'
import { foo } from 'mod'
import mod from 'mod'

(default export) import mod = require('mod') (for export = modules)

When esModuleInterop is false, prefer import * as path from 'path' instead of default imports.

No declaration files for third‑party packages

Run npm i @types/packagename -D. If none exist, create a simple declaration in typings/packagename.d.ts:

declare module 'packagename';

Class property initialization

Declare class fields before using them, e.g.:

class Person {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
}

For quick migration, you can temporarily use any but should replace it with proper interfaces later.

Implicit any and unused parameters

Explicitly type function parameters or rename unused ones to _ or prefix with an underscore.

‘this’ typing problems

Declare this as the first parameter in functions that use it:

export default function(this: any, one: string) {
  this.name = 'haha';
}

Step 6 – Debugging Configuration

Debug compiled dist files with a VSCode launch.json like:

{
  "configurations": [{
    "type": "node",
    "request": "launch",
    "name": "debug",
    "program": "/path/to/project/dist/cli.js",
    "args": ["xx"]
  }]
}

Or debug TypeScript directly using ts-node:

{
  "configurations": [{
    "type": "node",
    "request": "launch",
    "name": "debug",
    "runtimeArgs": ["-r", "ts-node/register"],
    "args": ["${workspaceFolder}/src/cli.ts", "xx"]
  }]
}

Step 7 – Strengthen Types and Eliminate any

Gradually replace any with proper interfaces or type aliases. While it’s unrealistic to remove every any in a JavaScript‑origin project, reducing them improves type safety and IDE assistance.

Conclusion

The guide demonstrates a practical workflow for converting a Node.js project to TypeScript, covering directory layout, tooling, common pitfalls, debugging, and incremental type improvement. Although the scope is limited to typical Node.js scenarios, the steps should be adaptable to many projects.

References

[1]

standard: https://standardjs.com/readme-zhcn.html [2] ts-node: https://github.com/TypeStrong/ts-node#visual-studio-code

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

migrationTypeScriptNode.jsESLinttsconfig
WecTeam
Written by

WecTeam

WecTeam (维C团) is the front‑end technology team of JD.com’s Jingxi business unit, focusing on front‑end engineering, web performance optimization, mini‑program and app development, serverless, multi‑platform reuse, and visual building.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.