Typescript node js project

Adding TypeScript-support to your Node.js project

Many Node.js projects will reach a level of complexity where we’ll often find ourselves wondering what a certain object’s structure looks like. We’ll also have the need for early warnings about errors due to trying to access fields that don’t exist or assuming different types from what they really are. These are good indications that you would derive a lot of benefit from using a type-checking system such as TypeScript. This article will look into how to make the transition from JavaScript to TypeScript in an existing project. TypeScript-support for Node.js is provided by the typescript NPM package. The best way to implement this package will depend on your project’s build tooling. If you have webpack set up, then the easiest way will be by using the ts-loader package (see the «Setting up ts-loader for webpack» section below for this ts-loader + typescript setup). However, if you don’t have a module bundler configured, then the simplest way to add TypeScript will be through the tsc («TypeScript compiler») command, which is included in the typescript package. This tsc setup is described next.

Setting up TypeScript compiler (tsc)

tsc is the official TypeScript transpiler which converts your TypeScript source files into JavaScript files that can be executed by Node.js or the browser. This section assumes you have a working Node.js project where you run your main js-file directly using node . The first order of business is adding the typescript package to your project as a dev-dependency:

npm install --save-dev typescript 
  • «noImplicitAny»: true — Disallows the use of the any type — a common anti-pattern in TypeScript.
  • «allowJs»: true — Allows us to have JavaScript (.js) files amongst the TypeScript (.ts) files. When we need to migrate an existing JavaScript project to TypeScript, this allows us to systematically convert files from JavaScript to TypeScript one at a time. Once the conversion is complete, this flag can be removed.
  • «outDir»: «dist» — The folder where the transpiled JavaScript files will be placed.
  • «rootDir»: «src» — The location of your TypeScript / JavaScript source code.
Читайте также:  Java основные функциональные интерфейсы

After adding these properties the tsconfig.json looks as follows:

And just like that, the code is ready to be compiled! Just run the command npx tsc and see the output files appear in the dist folder.

Before trying to run the compiled code, keep in mind that tsc outputs CommonJS-style JavaScript. This means that if your source code is written as ES modules, you need to change the «type» property in your package.json from «module» to «commonjs» in order to run the compiled code (tsc will still interpret your source code as ES modules). At this point the «main» .js file in the dist folder should run successfully via the node command: node dist/my-app.js

Source maps

A side-effect of running the compiled code instead of running the source code directly is that stack traces of errors will refer to the line numbers inside the compiled code instead of in the source code, which is not very helpful. Luckily we can have tsc generate source map files which map each line in the compiled code to the corresponding line in the source code. These can be used to make our application report the correct line numbers in error stack traces.

Getting tsc to generate the source map files is an easy matter of adding the «sourceMap»: true property to the «compilerOptions» in tsconfig.json:

Run npx tsc again and note that in the dist folder a .js.map file is created for each compiled .js file. However, we still need to make these mappings be interpreted at run-time. To do this, add the source-map-support package as a run-time dependency. We also add its types declaration package for TypeScript as a dev-dependency:

npm install --save source-map-support npm install --save-dev @types/source-map-support 

And activate it by adding the following to your main source file:

Compile and run the application. Error stack traces will now refer to the lines in the source code.

Adapting script commands

Creating script commands (in package.json) for compiling and running the application is pretty simple:

"build": "tsc", "run": "node dist/my-app.js", 

For a streamlined developer experience we would want to have a command that will listen for source file changes and then recompile and restart the application whenever they occur.

The tsc command conveniently has a —watch flag we can use to recompile. Then we can use the nodemon package to restart the application whenever we detect file changes in the dist folder (due to the recompilation). Hence we can have the following two scripts:

"build:watch": "tsc --watch", "run:watch": "nodemon dist/my-app.js --watch dist", 

But we need these two commands to run at the same time. This can be achieved using the npm-run-all package.

Add the required packages as dev-dependencies:

npm install --save-dev nodemon npm-run-all 
"build": "tsc", "run": "node dist/my-app.js", "build:watch": "tsc --watch", "run:watch": "nodemon dist/my-app.js --watch dist", "start": "npm-run-all --parallel build:watch run:watch" 

Run npm start to compile and run the application. Whenever you make a change to a source file, the application will automatically recompile and then restart.

Setting up ts-loader for webpack

If your application already has build tooling set up via webpack, the easiest way to add TypeScript support is by using the ts-loader package.

This time around, add the ts-loader and typescript packages as dev-dependencies:

npm install --save-dev ts-loader typescript 

The same tsconfig.json configuration file as above can be used in this case:

Note that in this case, since webpack is already configured to process JavaScript source files, there is no need for including the «allowJs»: true flag here, unless you would like both JavaScript and TypeScript files to be processed by ts-loader. If this is the case, make sure to include the extension js in the «test» property of the rule added to webpack.config.js below.

In webpack.config.js add a rule telling webpack to invoke ts-loader for all TypeScript files:

At this point the application should build and run fine. We are now ready to start converting .js files to .ts files.

Migrating existing JavaScript files to TypeScript

At this point we should have a tooling setup capable of compiling a combination of JavaScript and TypeScript files. This means we can systematically convert JavaScript files to TypeScript one at a time, compiling and testing the application along the way by renaming a .js file to .ts and fixing the compiler errors as they come up. Once all .js files in the project have been converted, the «allowJs»: true flag in the tsconfig.json can be removed.

Here are some general notes to observe during this conversion:

use strict

Any ‘use strict’ directives in existing JavaScript files can be removed since the «strict»: true setting in the tsconfig.json causes ‘use strict’ to be generated into the compiled JavaScript files automatically.

Extending the Error class

If you have defined any sub-classes of Error , note that there is a known bug in TypeScript whereby testing for an instance of this error using instanceof will not work.

See this StackOverflow post for a work-around. If you have multiple sub-classes of Error , I would recommend applying the work-around to a common «base» error class (eg. class ErrorBase extends Error ) and have all other error classes extend this class.

Alternatively, if your code need not support running on IE 11, you should be able to safely change the compiler target from ES5 to ES6 by changing the «target» property in tsconfig.json to «es6» (see the ES6 compatibility chart). This way tsc will generate all classes as actual ES-classes in the target code, effectively circumventing the bug and obviating the need for the work-around.

Conclusion

There are many benefits to TypeScript that make it worthwhile to take the time to set it up for new projects, and even to convert from JavaScript in existing projects. Making the necessary changes to an existing project’s build tooling is generally quite simple, and for new projects there is no need to add a module bundler just to be able to use TypeScript, thanks to tsc.

I have applied this migration to a project from my other articles. Feel free to view the version with the tsc setup or the version with the webpack / ts-loader setup on GitHub.

Источник

Node.js with TypeScript

Find out why TypeScript is an awesome tool and learn to use it by yourself.

TypeScript is a trendy open-source language maintained and developed by Microsoft. It’s loved and used by a lot of software developers around the world.

Basically, it’s a superset of JavaScript that adds new capabilities to the language. The most notable addition is static type definitions, something that is not present in plain JavaScript. Thanks to types, it’s possible, for example, to declare what kind of arguments we are expecting and what is returned exactly in our functions or what’s the exact shape of the object that we are creating. TypeScript is a really powerful tool and opens a new world of possibilities in JavaScript projects. It makes our code more secure and robust by preventing many bugs before the code is even shipped — it catches problems during code development and integrates wonderfully with code editors like Visual Studio Code.

We can talk about other TypeScript benefits later, let’s see some examples now!

Take a look at this code snippet and then we can unpack it together:

The first part (with the type keyword) is responsible for declaring our custom object type representing users. Later we utilize this newly created type to create function isAdult that accepts one argument of type User and returns boolean . After this, we create justine , our example data that can be used for calling the previously defined function. Finally, we create a new variable with information on whether justine is an adult.

There are additional things about this example that you should know. Firstly, if we would not comply with declared types, TypeScript would alarm us that something is wrong and prevent misuse. Secondly, not everything must be typed explicitly — TypeScript is very smart and can deduce types for us. For example, variable isJustineAnAdult would be of type boolean even if we didn’t type it explicitly or justine would be valid argument for our function even if we didn’t declare this variable as of User type.

Okay, so we have some TypeScript code. Now how do we run it?

First thing to do is to install TypeScript in our project:

Now we can compile it to JavaScript using tsc command in the terminal. Let’s do it!

Assuming that our file is named example.ts , the command would look like:

npx here stands for Node Package Execute. This tool allows us to run TypeScript’s compiler without installing it globally.

tsc is the TypeScript compiler which will take our TypeScript code and compile it to JavaScript. This command will result in a new file named example.js that we can run using Node.js. Now when we know how to compile and run TypeScript code let’s see TypeScript bug-preventing capabilities in action!

This is how we will modify our code:

And this is what TypeScript has to say about this:

As you can see TypeScript successfully prevents us from shipping code that could work unexpectedly. That’s wonderful!

TypeScript offers a whole lot of other great mechanisms like interfaces, classes, utility types and so on. Also, on bigger projects you can declare your TypeScript compiler configuration in a separate file and granularly adjust how it works, how strict it is and where it stores compiled files for example. You can read more about all this awesome stuff in the official TypeScript docs.

Some of the other benefits of TypeScript that are worth mentioning are that it can be adopted progressively, it helps making code more readable and understandable and it allows developers to use modern language features while shipping code for older Node.js versions.

TypeScript in the Node.js world

TypeScript is well-established in the Node.js world and used by many companies, open-source projects, tools and frameworks. Some of the notable examples of open-source projects using TypeScript are:

  • NestJS — robust and fully-featured framework that makes creating scalable and well-architected systems easy and pleasant
  • TypeORM — great ORM influenced by other well-known tools from other languages like Hibernate, Doctrine or Entity Framework
  • Prisma — next-generation ORM featuring a declarative data model, generated migrations and fully type-safe database queries
  • RxJS — widely used library for reactive programming
  • AdonisJS — A fully featured web framework with Node.js
  • FoalTs — The Elegant Nodejs Framework

And many, many more great projects. Maybe even your next one!

Источник

Оцените статью