2

Say you need to use a typescript/node library, inside an internal module, which is spread across multiple .ts files.

ApiRepositoryHelper.ts

import * as requestPromise from "request-promise"; 
module ApiHelper {
   class ApiRepositoryHelper extends DataRepositoryHelper {}
}

DataRepositoryHelper.ts

module ApiHelper {
   class DataRepositoryHelper {}
}

As soon as I add the line: import * as requestPromise from "request-promise";, the DataRepositoryHelper becomes inaccessible. What is the solution?

Observations:

Correct me if I'm wrong:

  1. Typescript internal modules can be split across multiple files.
  2. Typescript external modules can not.
  3. If you add a reference to an external module (say jQuery) outside the scope of your internal module (called 'A'), within the same file, you can use JQuery within A. But then your internal module 'A' becomes inaccessible across the rest of the project.
  4. If you have an external module, you can reference other external modules.
  5. You cannot reference the external module within the internal module scope, you will get "Import declarations in a namespace cannot reference a module."

I've read: Correct way to reference modules from other modules in Typescript.

I've also read:

Internal Module does not work if it has an import statement before it, but I don't agree with:

you can organise your code really well without internal modules

Simply because,

module ApiHelper {
 class myClass {}
}

is neater than,

import {Model} from "../../../lib/interfaces/model/Model";
import {List} from "../../../lib/classes/helper/List";
import {Serializable} from "../../interfaces/model/Serializable";
import {DataRepository} from "../../../lib/interfaces/data/DataRepository";
import {ModelFactory} from "../../interfaces/model/modelFactory";
import {DefaultApiParser} from "./DefaultApiParser";
import {ApiItemParser} from "./ApiParser";
//Insert two hundred other imports here...

export class MyClass{}

Also, using modules is superior, in my opinion, because you are not using the filesystem to reference your classes (this is the recommended way?!) - but just splitting them up and not caring where they are.

Community
  • 1
  • 1
David
  • 15,652
  • 26
  • 115
  • 156
  • Also, you can't compile your codebase into a single "executable" with external modules. Yes, purely from an application development perspective internal modules easily triumph external modules, but many people see Typescript just as something to make Javascript more easily with. Therefore there is more emphasis on Javascript inherited concepts, among which external modules (or simply modules) play an important part. Combining the two is a _mess_. You are basically _forced_ to use external modules across your whole code if you'd wish to import a module as such. – John Weisz Feb 23 '16 at 19:34

1 Answers1

1

Trust us ! (the ones who tried and burned themselves), modules/namespaces are best avoided when you can.

Using them may have you tackle a lot of uninteresting problems like

Also "neater" is debatable

  • If that can make you feel better Java developers have had - years before Typescript even existed - many imports at the top of their files and I hope that their life expectancy is not shorter than that of Javascript developers (being one of them too). More seriously some IDEs like Webstorm (12 EAP) handle imports automatically for you and even fold them in the editor so that they do not "pollute" the view of your code.

  • Also what your are doing, somehow, is an import * and not importing what you just require is debatable from a code design perspective.

Isolation, overall, is better with external modules.

Now suppose that your code is separated in two: API and implementation, and you would like to import all API definitions at once in the implementation classes in order to avoid multiple import statements.

It is possible in the API "section" to create an api.ts file that re-exports everything i.e

export * from 'interfaces/model/Model' 
export * from 'interfaces/model/Interfaces'
export * from 'interfaces/model/Serializables'
...

Then in the implementation classes simply import the single api.tsfile under a namespace e.g;

import * as api from '../api/api.ts'

It is then possible to access all the API defined exports as api.List, api.MyModel, etc...

But since you are at it why not go all the way and create an external module for your APIs definitions ? :)

Creating a Library

Unfortunately I cannot find a definitive resource on this for the moment.

The TL;DR to create a library is:

  • create an index.ts that re-exports all the definitions you want to expose in your library
  • compile the library files with the --declaration flag to automatically generate the typings
  • add a typings entry to package.json pointing to the generated index.d.ts file

To use the library:

  • drop it in the node_modules folder like any other library
  • simply import * as mylib from 'mylib': it will automatically import all the exported definitions and the typings

There is a brief mention here

You can also look at the Library and Usage paragraphs of what I wrote there

If I find any better resource, I will update this answer

Community
  • 1
  • 1
Bruno Grieder
  • 28,128
  • 8
  • 69
  • 101
  • 1
    Thanks! Is there any tutorial that points towards creating a typescript library, how to structure stuff, what to use, best practices, etc? I'm sure the guys writing tslint, angular, etc... have a lot to share, but I can't find anything! – David Feb 24 '16 at 08:37
  • You are welcome. See the added paragraph: *Creating a Library* above – Bruno Grieder Feb 24 '16 at 09:05