typescript

TypeScript recommended project structure with modules


I am a TypeScript beginner, but I have development experience in Java, and I'm wondering what is the recommended file structure for writing in TypeScript - especially when it comes to modules.

Let's say that I have several modules: ui.dashboard, ui.models, util.events, and util.common.

Each of these modules may contain several classes. In Java I would have the following file structure (where <base> is a base package for the project e.g., com.my.app):

src/<base>/ui/dashboard/<file per class>
src/<base>/ui/models/<file per class>
src/<base>/util/events/<file per class> 
src/<base>/util/common/<file per class>`

On the other hand, in TypeScript I see two main ways to accomplish the same thing:

Flat design:

src/ui.dashboard.js
src/ui.models.js
src/util.events.js
src/util.common.js

Here each file contains a module definition with all the relevant classes. This is OK, but then the files become huge and harder to manage.

Hierarchical design

In this design I would organize the files just like in Java, but since TypeScript (to the best of my knowledge) does not support declaring modules across files, I will have to write a gulp/grunt task that will combine the files into modules in build time.

As a Java programmer, this looks much more elegant, but then I lose some tooling support since the modules are not actually defined until build time, and therefore are not visible to the editor/IDE.

What is the recommended way to work?


Solution

  • Use both :) ES6 supports both named exports and default exports so both designs can be used as necessary.

    The overall structure of the project should use the hierarchical design for the reasons you stated, but flat modules should also be used as necessary. Especially for packages that will be incorporated into other codebases.

    For example:

    src/ui/dashboard/Class1.ts
    src/ui/dashboard/Class2.ts
    src/ui.dashboard.ts
    

    The src/ui/dashboard/Class1.ts file would look like:

    export class Class1 {}
    

    The src/ui.dashboard.ts file would look like:

    import {Class1} from './ui/dashboard/Class1';
    import {Class2} from './ui/dashboard/Class2';
    
    export default {
        Class1: Class1,
        Class2: Class2,
        randomFunction: () => {},
    }
    

    However, when in doubt fallback to default exports.

    ECMAScript 6 favors the single/default export style, and gives the sweetest syntax to importing the default. Importing named exports can and even should be slightly less concise. https://esdiscuss.org/topic/moduleimport#content-0