VueやReactでTypeScriptを使ってると、定数や関数のまとめ方に悩むことがしばしば出てくる。

こういうのはアプリケーションの設計や構造に依存する部分が大きいが、個人的に一番使いやすかった方法のメモ。

まずは前提知識。

例えば何らかのenum定数・関数の括りとしてUserPostに分けるとする。

Userモジュール

enum系

// modules/user/constant.ts
export const ROLE_TYPE = {
  ADMIN: 1,
  ANONYMOUS: 2,
} as const

型系

// modules/user/type.ts
import { ROLE_TYPE } from './constant'

export type RoleType = typeof ROLE_TYPE[keyof typeof ROLE_TYPE]

ユーティリティ関数系

// modules/user/util.ts
import { ROLE_TYPE } from './constant'
import { RoleType } from './type'

export const isAdminUser = (type: RoleType): type is Extract<RoleType, typeof ROLE_TYPE.ADMIN> => type === ROLE_TYPE.ADMIN

1ファイルのインポートで全てまるっと使えるようにindex作成

export * from './constant'
export * from './type'
export * from './util'

Postモジュール

Postも同様に

// modules/post/constant.ts
export const POST_TYPE = {
  IMAGE: 1,
  AUDIO: 2,
} as const

// modules/post/type.ts
import { POST_TYPE } from './constant'

export type PostType = typeof POST_TYPE[keyof typeof POST_TYPE]

// modules/post/util.ts
import { POST_TYPE } from './constant'
import { PostType } from './type'

export const existPost = (type: unknown): type is PostType => type === POST_TYPE.IMAGE || type === POST_TYPE.AUDIO

// modules/post/index.ts
export * from './constant'
export * from './type'
export * from './util'

各モジュール毎にまとめたら、最後に直下にindexを置いて各モジュールに名前を付け、親を定義する。

// modules/index.ts
import * as UserModule from './user'
import * as PostModule from './post'

export namespace Module {
  export import User = UserModule
  export import Post = PostModule
}

こうしておくと、実際に使う時には

<!-- vueファイル -->
<script lang="ts">
import Vue from 'vue'
import { Module } from '@/modules'

export default Vue.extend({
  computed: {
    ROLE_TYPE: () => Module.User.ROLE_TYPE
  },
  methods: {
    post (type: Module.Post.PostType | null) {
      if (!Module.Post.existPost(type)) return
      ...
    }
  },
})
</script>

インテリセンスさえちゃんと効いていれば、こんな感じに親をインポートするだけで型や変数も空間ごとに候補から探しながら実装できる。
ただ同じような記述が増えるので気になる人にはめっぽうダメなやり方かもしれない。

classを使えば継承などでもっと様々なアプローチが可能になりますが、既存のサービスに適用していく場合、隅々までは考慮できないケースがほとんどだと思うので、まずは独立しているそれぞれの定義を薄ーくまとめるような形にしてます。

所謂ゆるふわ。設計マスターには怒られそうだけど。

ただフォルダ構成さえ変えなければ現存のソースコードもそのまま機能するので少しずつ見直す際にはお役に立てるかもです。

プロフィール画像

ふじわら

よくわからないもので戯れてたら自分のことすらよくわからない人間になってしまいました。

ひっそりYouTubeしてます。