TypeScript var vs import

TypeScript import keyword has several usages, some depending on the environment, explaining why it's confusing. Let's see that with the minimum detail level (cause in real project it can be even more complex):

Modules CommonJs / Node

@mfc: This is the case that corresponds to your question.

The TypeScript project is using CommonJs modules, typically a node project:

// tsconfig.json
{
    "compilerOptions": {
        "module": "commonjs",
        ...
    }
}

In this context, import _ = require('http'); (version #1) is transpiled to var _ = require('http'); (version #2). So version #1 is the TypeScript syntax whereas version #2 is the JavaScript syntax.

require() is supported in version 1 but not in version #2 (error [ts] Cannot find name 'require'.) unless adding node typings to the project via npm i @types/node --save-dev (see this stackoverflow Q/A).

Modules ES6

@mfc: This is not the case you've asked for. But it's in Trott's answer so I've taken it into account.

import is the ES6 keyword and has its own syntax:

  • "Full" import of named exports: import * as lib from 'lib';
  • "Picking" import of named exports: import { square, diag } from 'lib';
  • Import of the default export: import myFunc from 'myFunc';

These imports are transpiled differently according to the module compiler option mentioned above:

  • ES6 → no change
  • CommonJSvar ... = require('...');
  • AMDdefine(...);

Namespaces

Alias

@mfc: This is not the case you've asked for. But it's in Jose A's answer so I've added here to have the full picture.

In a namespace, formerly called "(internal) module", import is used to create an alias, a shortcut to an exported element of another namespace.

namespace Root.Branch.Leaf {
    export const configPath = '...';
}

namespace LeafClient {
    import configPath = Root.Branch.Leaf.configPath;
    console.log(`configPath=${configPath}`);
}

The line import configPath = Root.Branch.Leaf.configPath; is transpiled into var configPath = Root.Branch.Leaf.configPath;, cf. TypeScript PlayGround.

Watch out for usages outside a namespace, since it created global variables!

Global module

Some libraries modify the global object (the window global variable in a browser), for instance:

  • jQuery and its $ global variable,
  • reflect-metadata to extends Reflect.

ES6 syntax also allows to load this kind of library using a side effects only import: import "reflect-metadata";

TypeScript supports this kind of imports. The compiler will try to fetch the corresponding typing definition to understand the library effects, for instance the new method Reflect.getMetadata().


Your import statement is TypeScript and will not run as-is in Node. You will need to compile (transpile?) it to JavaScript first. You can read the TypeScript docs for more info about how the TypeScript import keyword works. See the "Using Modules" subsection of the "Namespaces and Modules" section of the TypeScript handbook.

There is an import keyword in JavaScript too, but it doesn't work the way TypeScript's import works. It will only work in versions of Node that support ES6 modules. There are differences between this import and require that you can read about at "ES6 Modules: The Final Syntax". That import is something you can compare/contrast with require but not really var.


I had the same inquiry. Just found this in the "Alias" section of Typescript:

This is similar to using var, but also works on the type and namespace meanings of the imported symbol. Importantly, for values, import is a distinct reference from the original symbol, so changes to an aliased var will not be reflected in the original variable

https://www.typescriptlang.org/docs/handbook/namespaces.html#aliases

Tags:

Typescript