Lu4 Lu4 - 4 months ago 103
TypeScript Question

TypeScript for NodeJS via SystemJS

I would like to use TypeScript in my NodeJS app. In order to do that I've thought it would be nice to use SystemJS to make it transpile my source files on the fly to JavaScript. I've managed to bypass most of the issues related to SystemJS configuration except the following:

How to make SystemJS to prevent processing certain imports and make it use original


SystemJS via it's own
implementation wraps everything in it's own module representation disrespecting the original type of the module. It makes such NodeJS module as
an object rather than the function (the problem is in the code below)

'use strict';

console.log('In server.ts');

if ('production' === process.env.NODE_ENV)

let PORT = process.env.PORT || 3333;

import * as fs from 'fs';
import * as os from 'os';
import * as https from 'https';
import * as express from 'express'; // <------------- SystemJS makes express an object
import * as socketio from '';

import { Routes } from './routes/index';
import { DBConfig } from './config/db.conf';
import { RoutesConfig } from './config/routes.conf';
import { SocketServer } from "./reflex/SocketServer";

const app = express(); // <------------ This is object, so no way to initialize

Routes.init(app, express.Router());

const opts = {
key: fs.readFileSync(__dirname + '/cert/server.key'),
cert: fs.readFileSync(__dirname + '/cert/server.crt')

let server = https.createServer(opts, <any>app);
let socket = socketio(server, { transports: ['websocket'] });

let socketServer = new SocketServer(100, socket);

server.listen(PORT, () => {
console.log(`Application is up and running @: ${os.hostname()} on port: ${PORT}`);
console.log(`enviroment: ${process.env.NODE_ENV}`);

Another problem is that by replacing original require, not only every module should be covered with SystemJS configuration but also every submodule which is an overkill.

Here's my SystemJS config:

transpiler: 'typescript',
defaultJSExtensions: false,
map: {
// ------ system modules ------

"console": "@node/console",
"buffer": "@node/buffer",
"querystring": "@node/querystring",
"events": "@node/events",
"http": "@node/http",
"cluster": "@node/cluster",
"zlib": "@node/zlib",
"os": "@node/os",
"https": "@node/https",
"punycode": "@node/punycode",
"repl": "@node/repl",
"readline": "@node/readline",
"vm": "@node/vm",
"child_process": "@node/child_process",
"url": "@node/url",
"dns": "@node/dns",
"net": "@node/net",
"dgram": "@node/dgram",
"fs": "@node/fs",
"path": "@node/path",
"string_decoder": "@node/string_decoder",
"tls": "@node/tls",
"crypto": "@node/crypto",
"stream": "@node/stream",
"util": "@node/util",
"assert": "@node/assert",
"tty": "@node/tty",
"domain": "@node/domain",
"constants": "@node/constants",

// ------ common modules ------
'helmet': '@node/helmet',
'morgan': '@node/morgan',
'express': '@node/express',
'mongoose': '@node/mongoose',

'': '@node/',
'': '@node/', // <----- this module is being referenced by ''
'body-parser': '@node/body-parser',

// ------ SystemJS configuration ------
json: './node_modules/systemjs-plugin-json/json.js'

meta: {
'*.json': {
loader: 'json'
paths: {
'typescript': './node_modules/typescript',
packages: {
'typescript': {
main: 'lib/typescript'
'server': {
defaultExtension: 'ts'
typescriptOptions: tsconfig

So the question is the following: how to make SystemJS ignore certain imports (via configuration) and bypass control to native NodeJS

Thank you in advance!


If you take a look at how express.js exports things, you will see

exports = module.exports = createApplication;

and then

exports.application = proto;
exports.request = req;
exports.response = res;

When SystemJS converts this to a module, the function that you need, createApplication, becomes a default export.

There is a shorthand syntax for importing only the default value

import express from 'express';

console.log(typeof express); // function

Of course all the properties assigned to it - application, request etc. - are still available.

Or, if you prefer your original form for import, you can access it as default property

import * as express from 'express';

console.log(typeof express.default); // function

Now to your question

how to make SystemJS ignore certain imports (via configuration) and bypass control to native NodeJS require implementation?

There is no such option in the configuration AFAIK, but SystemJS provides original node require as System._nodeRequire, so you can use this as fallback in the code:

var express = System._nodeRequire('express');