Typescript es6 import module "File is not a module error" Typescript es6 import module "File is not a module error" typescript typescript

Typescript es6 import module "File is not a module error"


Extended - to provide more details based on some comments

The error

Error TS2306: File 'test.ts' is not a module.

Comes from the fact described here http://exploringjs.com/es6/ch_modules.html

17. Modules

This chapter explains how the built-in modules work in ECMAScript 6.

17.1 Overview

In ECMAScript 6, modules are stored in files. There is exactly onemodule per file and one file per module. You have two ways ofexporting things from a module. These two ways can be mixed, but it isusually better to use them separately.

17.1.1 Multiple named exports

There can be multiple named exports:

//------ lib.js ------export const sqrt = Math.sqrt;export function square(x) {    return x * x;}export function diag(x, y) {    return sqrt(square(x) + square(y));}...

17.1.2 Single default export

There can be a single default export. For example, a function:

//------ myFunc.js ------export default function () { ยทยทยท } // no semicolon!

Based on the above we need the export, as a part of the test.js file. Let's adjust the content of it like this:

// test.js - exporting es6export module App {  export class SomeClass {    getName(): string {      return 'name';    }  }  export class OtherClass {    getName(): string {      return 'name';    }  }}

And now we can import it with these thre ways:

import * as app1 from "./test";import app2 = require("./test");import {App} from "./test";

And we can consume imported stuff like this:

var a1: app1.App.SomeClass  = new app1.App.SomeClass();var a2: app1.App.OtherClass = new app1.App.OtherClass();var b1: app2.App.SomeClass  = new app2.App.SomeClass();var b2: app2.App.OtherClass = new app2.App.OtherClass();var c1: App.SomeClass  = new App.SomeClass();var c2: App.OtherClass = new App.OtherClass();

and call the method to see it in action:

console.log(a1.getName())console.log(a2.getName())console.log(b1.getName())console.log(b2.getName())console.log(c1.getName())console.log(c2.getName())

Original part is trying to help to reduce the amount of complexity in usage of the namespace

Original part:

I would really strongly suggest to check this Q & A:

How do I use namespaces with TypeScript external modules?

Let me cite the first sentence:

Do not use "namespaces" in external modules.

Don't do this.

Seriously. Stop.

...

In this case, we just do not need module inside of test.ts. This could be the content of it adjusted test.ts:

export class SomeClass{    getName(): string    {        return 'name';    }}

Read more here

Export =

In the previous example, when we consumed each validator, each module only exported one value. In cases like this, it's cumbersome to work with these symbols through their qualified name when a single identifier would do just as well.

The export = syntax specifies a single object that is exported from the module. This can be a class, interface, module, function, or enum. When imported, the exported symbol is consumed directly and is not qualified by any name.

we can later consume it like this:

import App = require('./test');var sc: App.SomeClass = new App.SomeClass();sc.getName();

Read more here:

Optional Module Loading and Other Advanced Loading Scenarios

In some cases, you may want to only load a module under some conditions. In TypeScript, we can use the pattern shown below to implement this and other advanced loading scenarios to directly invoke the module loaders without losing type safety.

The compiler detects whether each module is used in the emitted JavaScript. For modules that are only used as part of the type system, no require calls are emitted. This culling of unused references is a good performance optimization, and also allows for optional loading of those modules.

The core idea of the pattern is that the import id = require('...') statement gives us access to the types exposed by the external module. The module loader is invoked (through require) dynamically, as shown in the if blocks below. This leverages the reference-culling optimization so that the module is only loaded when needed. For this pattern to work, it's important that the symbol defined via import is only used in type positions (i.e. never in a position that would be emitted into the JavaScript).


Above answers are correct. But just in case...Got same error in VS Code. Had to re-save/recompile file that was throwing error.


How can I accomplish that?

Your example declares a TypeScript < 1.5 internal module, which is now called a namespace. The old module App {} syntax is now equivalent to namespace App {}. As a result, the following works:

// test.tsexport namespace App {    export class SomeClass {        getName(): string {            return 'name';        }    }}// main.tsimport { App } from './test';var a = new App.SomeClass();

That being said...

Try to avoid exporting namespaces and instead export modules (which were previously called external modules). If needs be you can use a namespace on import with the namespace import pattern like this:

// test.tsexport class SomeClass {    getName(): string {        return 'name';    }}// main.tsimport * as App from './test'; // namespace import patternvar a = new App.SomeClass();