Lets say we have the following 2 external modules in TypeScript:
export module My.Services.Common
{
export class Helper
{
//...
}
}
and
export module My.Services
{
export class Connection
{
//...
}
}
Now in my app.ts I would like to use both Connection and Helper classes. What I want to achieve is similar to the following code in C#:
using My.Services;
using My.Services.Common;
Or at least just
using My.Services;
But it looks like I cant work at the same time with both Helper and Connection. If I write:
import {My} from './services/common/Helper';
import {My} from './services/Connection;
Leads to error "duplicate identifier 'My'". That is logical though. So my question is how can I consume different classes from the same (or nested) modules?
My personal view on this is to break away from what you see in C# or Java (which maps more closely to internal modules) and treat it more like the external modules you are using...
Step 1. Ditch the module keyword. The file is a module already.
Step 2. Provide a non-dotted alias when you import.
Step 3. You can now import everything, '*', or specific classes when you import.
./services/common.ts
export class Helper
{
//...
}
./services.ts
export class Connection
{
//...
}
./app.ts
import * as Services from './services'
import { Connection } from './services/common'
var x = new Services.Helper();
var y = new Connection();
You can import multiple members from a module too:
import { Connection, Example } from './services/common'
var y = new Connection();
var z = new Example();
To add to Steve's good answer, since I've already drawn the ASCII art: The top-level object exported from this module, My, doesn't merge with any other object from other files named My. The only thing the My.Services.Common module achieves is making it more annoying to import Helper, because you have to fully qualify its name even though there's nothing else in there.
What you think you've done:
/-My--------------------\
| /-Services---------\ |
| | /-Common---\ | |
| | | [Helper] | | |
| | \----------/ | |
| | | |
| | [Connection] | |
| \------------------/ |
\-----------------------/
What you've actually done:
/-My---------------\ /-My---------------\
| /-Services-----\ | | /-Services-----\ |
| | /-Common---\ | | | | [Connection] | |
| | | [Helper] | | | | \--------------/ |
| | \----------/ | | \------------------/
| \--------------/ |
\------------------/
This is like having an organization system in your house where you have a dozen shoeboxes, each with a single smaller box inside it, each with a smaller box inside that one. The nested boxes provide no organizational benefit over the shoeboxes!
I have found another approach for tackling this organisation problem.
To go back to ASCII art (ᵔᴥᵔ)
My folder structure is so:
|
|-- myawesomemodule
| |
| |-- myawesomeclass.ts
| |-- myevenmoreawesomeclass.ts
| |-- myawesomemodule.ts
|
|-- myevenmoreawesomemodule
| |-- myotherclass.ts
| |-- myanotherclass.ts
| |-- myevenmoreawesomemodule.ts
|
index.ts
In myawesomemodule.ts, I do:
export {MyAwesomeClass} from './myawesomeclass'
export {MyEvenMoreAwesomeClass} from './myevenmoreawesomeclass'
Similarly in myevenmoreawesomemodule.ts, I do:
export {MyOtherClass} from './myotherclass'
export {MyAnotherClass} from './myanotherclass'
And finally at the root level in index.ts, I do:
import * as MyAwesomeModule from "./myawesomemodule/myawesomemodule";
import * as MyEvenMoreAwesomeModule from "./myevenmoreawesomemodule/myevenmoreawesomemodule";
export {MyAwesomeModule};
export {MyEvenMoreAwesomeModule};
Now I can ship this module off to a consumer, pack as NPM etc.
From a consumer, I do:
import MyPackage = require("mypackage"); //assuming you did npm pack
OR
import * as MyPackage from "./path/to/index" //assuming you didn't
Then I refer to my class names so:
let instance = new MyPackage.MyAwesomeModule.MyAwesomeClass();
I find this approach a bit better than exposing all my classes in a big module at the root level.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With