27 June 2017
When I started using TypeScript for my Angular applications, I was confused about all the different ways with which you could import other modules.
import './polyfills.ts';
import { Component } from '@angular/core';
import HomeComponent from './pages/home/home-page.component';
import * as _ from 'lodash';
import assert = require('assert');
At first, I thought that as a programmer you could choose whether you wanted to use curly braces or not, but I quickly found out that that was not the case. It all depends on how the module that you are importing is structured. I have created an overview of the different ways by which a module can be exported, together with their corresponding import syntax. Most of them are actually plain ECMAScript 2015 (ES6) module syntax that TypeScript uses as well. The examples are from my solution to the first puzzle of Advent of Code 2016 and can be found on GitHub if you want to play around with imports and exports yourself.
I've originally posted this article on https://blog.jdriven.com/2017/06/typescript-and-es6-import-syntax/
Named exports (TypeScript, ES6)
Export syntax
When a module needs to export multiple variables, it can use so-called named exports:
export const NORTH = new Direction(0, 1);
export function turnLeft(direction) {
return new Direction(-direction.dy, direction.dx);
}
Another way that named exports can be done is by specifying what you want to export at the end of the module:
const NORTH = new Direction(0, 1);
function turnLeft(direction) {
return new Direction(-direction.dy, direction.dx);
}
export { NORTH, turnLeft };
Import Syntax
You can import these modules in two ways. Either you import everything as one object (sometimes called namespace):
import * as taxicab from './taxicab';
const direction = taxicab.turnLeft(taxicab.NORTH);
Or, you specify all the individual variables that you want to import:
import { NORTH, turnLeft } from './taxicab';
const direction = turnLeft(NORTH);
If you specify the variables, you can also import them under a different name:
import { NORTH, turnLeft as left } from './taxicab';
const direction = left(NORTH);
Default export (TypeScript, ES6)
A module can also export one variable as the default export:
export default function shortestPath(instructions) {
}
This can be imported with the following syntax, without curly braces:
import shortestPath from './shortestPath';
const distance = shortestPath('R2 R2 L3');
This is implemented by exposing a named export with a special name 'default', so you could also do the following:
import { default as shortestPath } from './shortestPath';
If you need this to import a module that has both a default export and named exports, then this module might not have one single responsibility.
Empty import (TypeScript, ES6)
Some modules do not export any variables and only have side-effects, such as mutating the global window (global variables) or prototypes (e.g. polyfills). To execute the body of these modules, they can be imported without specifying any variable names. It will be executed only once, because modules in JavaScript are singletons.
import 'mocha';
describe('shortestPath', () => {});
NodeJS modules (TypeScript)
NodeJS modules are based on the CommonJS module standard (exports and require), augmented with some NodeJS specific syntax (module.exports for instance). In JavaScript, you can export things from your module by assigning them to the object exports and import then synchronously with require()
exports.equal = function equal(actual, expected, message) {
if (actual != expected) fail(actual, expected, message, '==', assert.equal);
};
const assert = require('assert');
assert.equal(shortestPath('R2, L3'), 5);
assert.bogusFunction();
This is also valid TypeScript, but the TypeScript compiler cannot help you with type information from the module. For this to work, you need to import the module, to let TypeScript find the type information from the module’s type definition file.
import assert = require('assert');
assert.equal(shortestPath('R2, L3'), 5);
// assert.bogusFunction(); -- Compile error: Property bogusFunction does not exist
If you let TypeScript compile to CommonJS modules, you can also use ES6 module syntax in your TypeScript source. However, because it has no default export, you have to import it as with named exports:
import * as assert from 'assert';
// or: import { equal } from 'assert';
More information
I hope this gives you an overview on how you should import the different module flavours in ES6 and TypeScript. For more details, have a look at the following resources that I’ve used to make this overview.
The very precise and thorough book "Exploring ES6" by Axel Rauschmayer
The official TypeScript handbook