Typescript - Organizing Modules in Vuex

Posted on August 28, 2018

I care about organizing folders because Javascript/Typescript doesn’t have the convenient module system like csharp’s or haskell’s module system. With these languages you can do

// csharp
using System.Linq;
using System.Collections.Generic;
-- haskell
import Control.Monad.Trans.Class
import Control.Monad.Trans.State

and you get the exported functions from these namespaces/modules. Unfortunately, in Typescript I have to know the relative path.

import { someUtilityFunction } from "../../../../../where-is-this-damn-file";

Initially it’s just annoying but when you have hundreds of components relying on a reusable component inside the project it becomes a mental overhead.

With Typescript projects I tend to use barrel files. Especially projects that are enormous. It makes it a bit easier to package modules.

So I organized my vuex modules a little different from what was suggested in Vuex’s Application Structure.

Here’s a contrived example of how I organize folders.

The action-types folder contains the actions types for the project (e.g const INCREMENT = "INCREMENT";). This action type will be used in different parts of the project depending on what will need this action type. So I have the action-types directory at the root level in the src directory. In addition to positioning this folder at the root level I make a barrel file for it.

// index.ts inside action-types folder
export * from "./count.types";

This will export everything in count.types.ts.

After making the barrel file I then add it in my tsconfig.json, in the path field. Like so

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/action-types": ["src/action-types"]
    }
  }
}

After setting up the tsconfig.json path field, I don’t have to reference the relative path when I’m importing action types. All I have to do is this

import { INCREMENT } from "@/action-types";

I import INCREMENT like this to every file that needs this action (e.g A Component/View that calls an action.). So far the only time I need to avoid this is when I’m importing from within the same parent folder.

parent-folder
  |- child-folder-1
     |- child-1.ts
  |- child-folder-2
     |- child-2.ts

child-1.ts can’t do import { someComponent } from "child-folder-2". If I do this, typescript will complain of circular dependencies.

Regarding vuex folder organization, the actions and mutations file will stay private inside the count folder where the module file is.

My overall folder structure looks like this.

main.ts
components/
views/
action-types/
  |- count.types.ts
  |- index.ts
store/
  |- index.ts
  |- store.ts
  |- modules/
    |- index.ts
    |- count
        |- index.ts
        |- count.actions.ts
        |- count.module.ts
        |- count.mutations.ts