I created this repo to demonstrate with a small example, how to migrate an existing Node.js project written in Javascript to Typescript. It was actually a basic application generated using the express-generator package, then it was slowly migrated to Typescript. The process to getting this done is outlined below.
You need to have Node.js installed
- Generate a basic application with express-generator.Visit the package page for instructions on how to do so.
- Navigate to the application folder in your terminal and run
npm install
to install all the dependencies.
- It is conventional to have your Typescript files in a
src
folder (it can be any name), which will be your working directory for Typescript files, so I created one in the project root folder. - I moved the
routes
andbin
folders intosrc
, and I also movedapp.js
too. This is because those are the Javascript files/folders we'll be working on. - Typescript compiles into Javascript, so you'll need the Typescript compiler. Even though you write your application in Typescript, what your server runs at the end is Javascript. You can install the Typescript compiler on your terminal as thus:
npm install -g typescript
. Voila! 🎉 You now have thetsc
command available for use in your terminal. More on that shortly. - The Typescript compiler needs a
tsconfig.json
file which tells it which files to compile (sometimes called the compilation context), and which compilation options to use. For this tutorial, create an emptytsconfig.json
file and copy/paste the contents in thetsconfig.json
in this repo there. - Change all Javascript files (including
www
) to Typescript files by changing the extensions from.js
to.ts
. - Hooray 🎉🎉🎉! Now you have successfuly migrated your application to Typscript. Now, let's start fixing those errors you see generated by the Typescript compiler. 💪🏼
-
Let's first look at
index.ts
in the routes folder. Notice there's an error:cannot find name require
. To solve this problem, you need to install Typescript Type Definition files for Node. Simply runnpm install @types/node --save-dev
in your terminal and you should see the error disappear. Now you should have a@types
folder in yournode_modules_
. All other type definition files will be installed in that folder. -
Next we have 3 errors:
Parameter 'req' implicitly has an 'any' type
.Parameter 'res' implicitly has an 'any' type
.Parameter 'next' implicitly has an 'any' type
.
To solve this, we'll take advantage of definition files by Node and Express.
- First install Express Type Definition files by running
npm install @types/express --save-dev
in your terminal. - Delete
var express = require('express');
and replace it withimport express, { Request, Response, NextFunction} from 'express';
- Delete
router.get('/', function(req, res, next)
and replace it withrouter.get('/', function(req: Request, res: Response, next: NextFunction)
. This basically enforces types for thereq
,res
andnext
parameters. Do this across the routes files andapp.ts
- Once that is done, we'll need change our code to use the
import
syntax, instead of therequire
syntax. I know things can still go well if you stick withrequire
, but it's advisable to useimport
except when you're not supposed to. The top section in yourapp.js
should look like this now:
import express, { Request, Response, NextFunction } from 'express';
import createError from 'http-errors';
import path from 'path';
import cookieParser from 'cookie-parser';
import { default as logger } from 'morgan';
Also update your routes to look like this:
export default router;
instead of module.exports = router
To import them in app.js
, change the require
syntax to:
import { default as index} from './routes/index';
import { default as users} from './routes/users';
-
Once you do this, you have a couple of errors:
could not find declaration file for <module>
. All you need to do is install type definitions for that module. Runnpm install @types/<module-name> --save-dev
. -
Also in
app.js
, you have an error:Parameter 'err' implicitly has an 'any' type
. What you need to to is specify theerr
paremeter type as Error as thus:err: Error
. -
This gives rise to another error within the error handler middleware:
Property 'status' does not exist on type 'Error'
. To fix this, we need to:
- Create an interface in a separate file
error.ts
that extendsError
and includes astatus
property, then export the interface. You can save the file in the root of thesrc
folder. Your file should have the following content:
export default interface Error {
status: number
}
-
Then, import the file we just created in
app.js
as thus:import Error from '../error'
. The error should go away now. -
The last errors should be in
www.ts
. What you need to do is:
- Import the Error interface as you did in Step 7.
- Update
error.ts
to look like this:
export default interface Error {
status: number,
message?: string,
syscall: string,
code: string
}
- Change `var app = require('../app');` to `import { default as app } from '../app'`
- Now, that's all, and your application is fully migrated to Typescript.
-
Run
tsc
in your terminal to build the application. You'll notice that there's a new folderdist
in your project root. -
Create a start script in
package.json
to run the app as thus:
"scripts": {
"start": "node ./dist/bin/www.js"
}
-
Run
npm run start
. -
You should have your app running on
http//localhost:3000
. You're live! 🎉🎉🎉
If you have any further question or issue, please feel free to open an issue in this repo.