How to set up Typescript compiler and editing environment with Node.js

; Date: June 2, 2019

Tags: Node.JS »»»» TypeScript

TypeScript is growing rapidly in popularity within the JavaScript ecosystem. Where interest in JavaScript interest is relatively flat, TypeScript popularity (gauged by Google Trends) is growing fast. TypeScript offers us important data type enforcement, implemented in the compiler, for what is otherwise JavaScript code. This is potentially attractive to any large project written in JavaScript. TypeScript is easy to use on the Node.js platform, so let's see how to do so.

In this article we'll see how to set up a proper coding environment in which we can code in TypeScript on the Node.js platform. Since the Typescript toolchain is written in Node.js, of course your first step is to install Node.js and npm (and yarn if you like). You probably already have Node.js installed, but if you need to learn about installing Node.js go to (nodejs.org) https://nodejs.org/en/download/package-manager/ We will be using Node.js version 10.x in this book because of its support for ES6 modules.

This is an excerpt from (www.amazon.com) Quick Start to using Typescript and TypeORM in Node.js applications.

This is part of a series including: (itnext.io) Choosing BetweenTypeScript vs JavaScript: Technology, Popularity

You can learn about Typescript from its website: (www.typescriptlang.org) https://www.typescriptlang.org/

You will learn from the Typescript quick start guide that one installs Typescript as so:

$ npm install -g ts-node typescript

The typescript package is recommended to be installed globally (the -g option). It installs the commands, tsc and ts-node, that are the Typescript compiler. The compilers generate JavaScript source from Typescript files. It is the JavaScript that will be executed, of course, and is what will be deployed to browsers or as Node.js modules.

While the official instructions are to install the compiler tools globally, let us explore local installation. Many of us prefer explicitly declared dependencies in package.json rather than relying on remembering to install tools globally. With explicitly declared dependencies the instructions are simply npm install, and everything gets installed. The other approach requires everyone to follow the multiple setup steps required, and what if they do it incorrectly?

This requires two steps, the first being to add ./node_modules/.bin to ones PATH variable like so:

$ export PATH="./node_modules/.bin:${PATH}"

This is a little trick to configure the shell to look for installed commands in the node_modules directory in addition to the regular commands in the PATH (e.g. /usr/bin).

The second step is to install such a package like so:

$ npm install typescript ts-node --save-dev

This is a local install, and by using --save-dev the dependency is added to the devDependencies section of package.json. The devDependencies are not installed when npm install is run in production mode, meaning either the --production flag is set or the NODE_ENV environment variable is set to production.

Either way you've installed TypeScript, you can now type this to see the usage instructions:

$ tsc --help

Another highly useful tool is ts-node, a variant of the node command that directly executes Typescript source. See: (www.npmjs.com) https://www.npmjs.com/package/ts-node

IDE Support for TypeScript

Several IDE's have support for TypeScript.

Initializing a Node.js project with TypeScript support

Actually, we got a little ahead of ourselves. Obviously if we're installing packages using --save-dev we must have a Node.js project set up. So... let's start this over.

Initialize a Node.js project:

$ mkdir project-name
$ cd project-name
$ npm init    (or yarn init)
... answer questions
$ npm install typescript ts-node --save-dev

That's more like it.

Another required piece is the TypeScript configuration file, tsconfig.json.

{
    "compilerOptions": {
        "lib": [ "es5", "es6", "es7",
                 "es2015", "es2016",
                 "es2017", "es2018",
                 "esnext" ],
        "target": "es2017",
        "module": "CommonJS",
        "moduleResolution": "Node"
    }
}

This configuration works for modern Node.js versions. With 10.x and later we have all the ES2015/2016/2017/2018 features we could want. Therefore when TypeScript compiles our code it should be using those features.

This says to include support for the ES5/ES6/etc specifications, which is what Node.js 10.x implements. It outputs code using the ES2017 specification, again that’s what is available in Node.js 10.x. By using es2017 as the target async/await functions are compiled using async/await keywords, rather than using Generator functions and the yield keyword.

The module flag says to generate code using the CommonJS format. This is the traditional Node.js module format.

The moduleResolution flag says to use the Node.js algorithm to find modules. Since we're looking to code for Node.js we need TypeScript to do this.

The compiler options are documented on the TypeScript website: (www.typescriptlang.org) https://www.typescriptlang.org/docs/handbook/compiler-options.html

There are many other options that could be useful, most of them turn on additional code quality checks.

Node.js type definitions for TypeScript

A very cool and most interesting feature of the TypeScript environment is the type definitions available both baked into the TypeScript runtime, and additional definitions available through the Definitely Typed project. ( (definitelytyped.org) http://definitelytyped.org/)

Unfortunately the Definitely Typed website does a poor job of explaining what it offers. This is a collection of type libraries for various tools and frameworks in the JavaScript ecosystem. These type libraries make it easier to use TypeScript with one of those tools or frameworks.

What that means is the type library for a given module helps the TypeScript compiler to know objects and functions and function parameters and more for that module.

Typescript includes a capability to implement a Declaration File whose purpose is to declare things. That’s what the Definitely Typed project does, is create well specified declaration files.

Adding the Definitely Typed definitions for Node.js brings in support for certain Node.js features.

$ npm install --save-dev @types/node

This brings in a number of Node.js useful definitions. You don't declare anything in your code. Instead the TypeScript compiler tools automatically pick up the type definitions you've imported.

The Definitely Typed project has a large library of type definitions, and the website has a little search engine to look up what's available. Just don't expect any documentation to help you know what's what.

Generating declaration files for JavaScript generated by TypeScript

Declaration files inform the TypeScript compiler about the types used in a JavaScript module. Otherwise the TypeScript compiler would be unable to offer much help when writing code against a JavaScript module. Therefore it is best for all JavaScript module authors to bundle TypeScript declaration files.

This applies to cases where we generate a JavaScript module from TypeScript source. Making the resulting module useful to TypeScript requires declaration files.

Unfortunately the declaration files documentation does not provide much help for a newcomer looking to create these files.

Fortunately the TypeScript compiler can generate declaration files.

In tsconfig.json add these declarations:

"declaration": true,
"declarationMap": true,
"inlineSourceMap": true,
"inlineSources": true,

Technically all that's required is the declaration setting, and the TypeScript compiler will generate the .d.ts file alongside the .js file.

The other settings add Source Map files which are a kind of index into the source files used in generating the JavaScript code. With an inline source map the source map data is presented as a comment at the tail end of the file.

What did we learn about TypeScript?

The TypeScript compiler tools run on the Node.js platform, and install just like any other Node.js package. Hence it is very easy to use TypeScript as part of a Node.js project.

The Definitely Typed project is a companion project to TypeScript. The TypeScript language supports what are called declaration files that inform the TypeScript about the types used in a JavaScript module. The TypeScript compiler can generate the declaration files for you, as we just learned, or you can implement your own.

The Definitely Typed project is a collection of well-specified declaration files for JavaScript projects that do not implement their own.