Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to wrap several TypeScript modules into groups for organization

My TypeScript project has grown in to a moderate size and I'm trying to come up with a good way to organize it.

Right now, the project (an Angular 1.x app) is has the following structure:

-app/
 |
 |-components/
 | |
 | |-component A/
 | | |
 | | |-(..models..).ts
 | | |-(..services..).ts
 | |
 | |-component B/
 | | |
 | | |-(..models..).ts
 | | |-(..directives..).ts
 | |
 | (...)
 | |
 | |-component Z/
 | | |
 | | |-(..directives..).ts
 | | |-(..services..).ts
 | |
 | |-components.ts
 |
 |-app.ts

Basically, I've grouped app components logically so for instance a Video component will have its models and services declared in a single directory. I then load import all the components into a single file app/components.ts and re-export them.

 // models
 export * from './componentA/models.ts';
 export * from './componentB/models.ts';
 export * from './componentC/models.ts';

 // services
 export * from './componentA/services.ts';
 export * from './componentX/services.ts';
 export * from './componentZ/services.ts';

 // directives
 export * from './componentB/directives.ts';
 export * from './componentY/directives.ts';
 export * from './componentZ/directives.ts';

I'd then import the app/components.ts file in each of the component as well, since I almost always required multiple components in every time and importing each one individually would get very repetitive.

 // app/components/componentA/services.ts
 import * as ProjectName from '../components.ts';

 export class ComponentA_Service1 extends ProjectName.BaseService {

     protected $http: ng.IHttpService;
     protected $log: ng.ILogService;
     protected configService: ProjectName.ConfigService;

     /** @ngInject */
     constructor($http: ng.IHttpService, $log: ng.ILogService, ConfigService: ProjectName.ConfigService) {

         this.$http = $http;
         this.$log = $lot;
         this.configService = ConfigService;
     }

     // (.....)
 }

 export class ComponentA_Service2 { /* ... */ }
 export class ComponentA_Service3 extends ProjectName.ComponentZ_Service4 { /* ... */ }

This worked out well for a while, but now since the project has several dozen classes and interfaces defined. ProjectName becomes cluttered with dozens of members.

What I'd like is to group together different members based on what they are. For instance, a structure like:

 namespace ProjectName {

     namespace Models {

         class ComponentA_Model1 { /* ... */ }
         class ComponentA_Model2 { /* ... */ }
         class ComponentB_Model1 { /* ... */ }
     }

     namespace Services {

         class ComponentA_Service1 { /* ... */ }
         class ComponentA_Service2 { /* ... */ }
         class ComponentZ_Service4 { /* ... */ }
     }

     namespace Directives {

         class ComponentB_Directive1 { /* ... */ }
         class ComponentY_Directive2 { /* ... */ }
         class ComponentZ_Directive3 { /* ... */ }
     }
 }

So far, I'm unable to figure out how to achieve that using TypeScript. More specifically, I'm unable to import several different modules and export them a single module.

Any ideas if it is even possible in TypeScript, or I'm heading in a completely wrong direction here?


Update (January 31, 2016): I thought I should add what I eventually ended up doing. I had already started trying an architecture similar to what was suggested by @Vadim Macagon below. While it is the correct solution for what I was looking to do, I ultimately decided against it because of the reasons pointed out by @mk. in the accepted answer below.

I'm now importing individual modules from their respective directories directly in each file. While it is certainly a slight overhead when writing code, it is still the better approach.

like image 509
Uzair Sajid Avatar asked Mar 13 '23 11:03

Uzair Sajid


1 Answers

You're already familiar with re-exporting, so I believe something like this should work:

// models.ts
export * from './componentA/models.ts';
export * from './componentB/models.ts';
export * from './componentC/models.ts';

// services.ts
export * from './componentA/services.ts';
export * from './componentX/services.ts';
export * from './componentZ/services.ts';

// directives.ts
export * from './componentB/directives.ts';
export * from './componentY/directives.ts';
export * from './componentZ/directives.ts';

// projectname.ts
import * as Models from './models';
import * as Services from './services';
import * as Directives from './directives';

export { Models, Services, Directives };

// app.ts
import { Models, Services, Directives } from './projectname';
// OR
import * as ProjectName from './projectname';
like image 75
Vadim Macagon Avatar answered Mar 16 '23 11:03

Vadim Macagon