TypeScript で 都道府県型を定義する

1. はじめに

カラダノートの 堀内 です。 前回 は電話番号型を定義してので、今回は都道府県を実装してみます。

2. ゴール

都道府県型を使って何を実現したいかというと、例えば、北海道と沖縄だけを対象とする処理を実装するときに、それ以外の都道府県だと型チェックでエラーを出したい、ということを目指します。

以下のようなイメージです。 ちなみに Prefecture<N> の Nは 都道府県コード に相当します。

  const hokkaido = Prefecture.from(1)   // Prefecture<1>
  const okinawa = Prefecture.from(47)  // Prefecture<47>
  const saitama = Prefecture.from(11)  // Prefecture<11>

  // 北海道と沖縄のみを対象とする処理
  const sendTo = (prefecture: Prefecture<1> | Prefecture<47>): void => {
    // do something ...
  }

  sendTo(hokkaido)
  sendTo(okinawa)
  sendTo(saitama)  // ここを型チェックでエラーを出したい

3. 実装

もういきなりですが以下のとおり実装しました。

/* prefecture.ts */

// 都道府県コード一覧
const PREFECTURE_CODES = [
  1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
  11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
  21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
  31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
  41, 42, 43, 44, 45, 46, 47
] as const

// 都道府県名一覧
const PREFECTURE_NAMES = [
  '北海道', '青森県', '岩手県', '宮城県', '秋田県', '山形県', '福島県', '茨城県', '栃木県', '群馬県',
  '埼玉県', '千葉県', '東京都', '神奈川県', '新潟県', '富山県', '石川県', '福井県', '山梨県', '長野県',
  '岐阜県', '静岡県', '愛知県', '三重県', '滋賀県', '京都府', '大阪府', '兵庫県', '奈良県', '和歌山県',
  '鳥取県', '島根県', '岡山県', '広島県', '山口県', '徳島県', '香川県', '愛媛県', '高知県', '福岡県',
  '佐賀県', '長崎県', '熊本県', '大分県', '宮崎県', '鹿児島県', '沖縄県'
] as const

// 都道府県コードのUnion型
export type PrefectureCode = typeof PREFECTURE_CODES[number]

// 都道府県名のUnion型
export type PrefectureName = typeof PREFECTURE_NAMES[number]

// 都道府県コードの検証
const validate = (value: PrefectureCode): boolean => {
  return PREFECTURE_CODES.includes(value)
}

// 都道府県型
export type Prefecture<Code extends PrefectureCode> = {
  readonly code: Code
  readonly name: PrefectureName
}

// 都道府県型の生成
export const Prefecture = {
  from<T extends PrefectureCode>(value: T): Prefecture<T> {
    if (!validate(value)) {
      throw new Error(`${value}は都道府県コードではありません`)
    }

    return {
      code: value, 
      name: PREFECTURE_NAMES[value - 1]
    }
  }
}

export default Prefecture

で、ゴールのところでで書いたコードで動きを確認してみると、埼玉が型チェックでエラーになっています。

f:id:karadanote:20210405131545p:plain

ドメイン知識をこんな感じで型定義にどんどん集めていきたい。 的なドメイン駆動設計をやりたい方をカラダノートでは募集しております。

herp.careers

herp.careers