Modules in Typescript

It’s not the why, but more on what of ‘modules’.

No Javascript is an island. It was an island about two decades back but Javascript has done some pretty good land reclaimation to form large continents now.

So it goes without saying that these are not the days of writing Javascript or Typescript in <script> tag in a single HTML. A typical project has hundreds of packages and a lot of code written by you and others who hate you.

While it can be easy enough to split code in separate files to try maintaining them - they can get confusing and a bit dangerous since everyone has access to global scope.

Ergo, modules.

Modules provide a convenient way to split code and keep everything incl. scope tidy. Let’s see some examples on how we can create and use modules.

Export a function / variable

A module is typically written in its own file, and thereon affectionately called as “external module”.

An external module has what is called “top level export”. The export statement is at the file level and is not under a class or function.

An “internal module” is no more called that, but is called “namespaces”. We will deal with it at a later time.

Consider a simple example of an external module -

// math-op.ts

const double = 2;

function getSumDouble(x: number, y: number) {
  return (x + y) ** double;
}

export = {
  getSumDoub: getSumDouble
};

The code block is introduced in a separate file - it brings not only code clarity and readability due to lesser code, but also narrower scope.

The export statement tells the module what exactly is available to other files that import this module. We are just exporting a single function from the file, but we could export everything as well.

Let’s see how we can consume the module -

// Caller.ts
import MathOp = require("./math-op");

console.log(MathOp.getSumDoub(1, 2));
// 9

We just use a variable math, import the module to that variable and use the exported function. The usage is “normal” and does not introduce any complexities!

Let’s now try to access double, which is a variable in math-op.ts.

// Caller.ts

//  ...

console.log(MathOp.double);
// error TS2339: Property 'double' does not exist on type '{ getSumDoub: (x: number, y: number) => number; }'

Any variable or method which is not exported from the module stay local to that module.

We can export the variable also, if required.

// math-op.ts

//  ...

export = {
  getSumDoub: getSumDouble,
  double: double
};

Now, we can get the value from the external file.

// Caller.ts

console.log(MathOp.double);
// 2

Export a class

A more common pattern that you see in the real world is exporting classes.

The module is rewritten to contain and export a class. You can then use that class and access its members and variables.

// math-op.ts

export class MathThis {
  private double = 2;

  getSumDouble(x: number, y: number) {
    return (x + y) ** this.double;
  }
}

You can call and use this class like so -

// Caller.ts

import MathOp = require("./math-op");

const mathMatters = new MathOp.MathThis();
console.log(mathMatters.getSumDouble(1, 2));
// 9
comments powered by Disqus