【NestJS】都道府県のマスタをDBではなくクラス定数で管理するようにした件

# 概要

プロジェクトで都道府県情報をDBで管理せずにクラス定数で管理するようにした際の知見をまとめる

# 都道府県情報を取得するためのクラスを作成

```ts:masters/master.ts
export class Master {
  private readonly masters: IMaster[]
  constructor(masters: IMaster[]) {
    this.masters = masters
  }

  findNameById(id: number) {
    return this.masters.find((v) => v.id === Number(id))
  }

  findIdByName(name: string) {
    return this.masters.find((v) => v.name === name)
  }

  findAll(order_by?: 'ASC' | 'DESC') {
    if (order_by === 'DESC') {
      return this.masters.sort((a, b) => {
        return b.id - a.id
      })
    }
    return this.masters
  }

  getLength() {
    return this.masters.length
  }

  existsById(id: number): boolean {
    return !!this.masters.find((v) => v.id === Number(id))
  }

  getMaxIdObject() {
    const id = this.masters
      .map((v) => v.id)
      .reduce((a, b) => {
        return Math.max(a, b)
      })

    return this.masters.find((v) => v.id === Number(id))
  }

  getMinIdObject() {
    const id = this.masters
      .map((v) => v.id)
      .reduce((a, b) => {
        return Math.min(a, b)
      })

    return this.masters.find((v) => v.id === Number(id))
  }
}

export interface IMaster {
  id: number
  name: string
}

```

## 解説

都道府県ID：都道府県名をセットで管理するので`Interface`を用意します

```ts
export interface IMaster {
  id: number
  name: string
}
```

# 都道府県マスターを作成

```ts:masters/prefecture.master.ts
import { IMaster, Master } from './master.master'

const PREFECTURE: IMaster[] = [
  {
    id: 1,
    name: '北海道',
  },
  {
    id: 2,
    name: '青森県',
  },
  {
    id: 3,
    name: '岩手県',
  },
  {
    id: 4,
    name: '宮城県',
  },
  {
    id: 5,
    name: '秋田県',
  },
  {
    id: 6,
    name: '山形県',
  },
  {
    id: 7,
    name: '福島県',
  },
  {
    id: 8,
    name: '茨城県',
  },
  {
    id: 9,
    name: '栃木県',
  },
  {
    id: 10,
    name: '群馬県',
  },
  {
    id: 11,
    name: '埼玉県',
  },
  {
    id: 12,
    name: '千葉県',
  },
  {
    id: 13,
    name: '東京都',
  },
  {
    id: 14,
    name: '神奈川県',
  },
  {
    id: 15,
    name: '山梨県',
  },
  {
    id: 16,
    name: '長野県',
  },
  {
    id: 17,
    name: '新潟県',
  },
  {
    id: 18,
    name: '富山県',
  },
  {
    id: 19,
    name: '石川県',
  },
  {
    id: 20,
    name: '福井県',
  },
  {
    id: 21,
    name: '岐阜県',
  },
  {
    id: 22,
    name: '静岡県',
  },
  {
    id: 23,
    name: '愛知県',
  },
  {
    id: 24,
    name: '三重県',
  },
  {
    id: 25,
    name: '滋賀県',
  },
  {
    id: 26,
    name: '京都府',
  },
  {
    id: 27,
    name: '大阪府',
  },
  {
    id: 28,
    name: '兵庫県',
  },
  {
    id: 29,
    name: '奈良県',
  },
  {
    id: 30,
    name: '和歌山県',
  },
  {
    id: 31,
    name: '鳥取県',
  },
  {
    id: 32,
    name: '島根県',
  },
  {
    id: 33,
    name: '岡山県',
  },
  {
    id: 34,
    name: '広島県',
  },
  {
    id: 35,
    name: '山口県',
  },
  {
    id: 36,
    name: '徳島県',
  },
  {
    id: 37,
    name: '香川県',
  },
  {
    id: 38,
    name: '愛媛県',
  },
  {
    id: 39,
    name: '高知県',
  },
  {
    id: 40,
    name: '福岡県',
  },
  {
    id: 41,
    name: '佐賀県',
  },
  {
    id: 42,
    name: '長崎県',
  },
  {
    id: 43,
    name: '熊本県',
  },
  {
    id: 44,
    name: '大分県',
  },
  {
    id: 45,
    name: '宮崎県',
  },
  {
    id: 46,
    name: '鹿児島県',
  },
  {
    id: 47,
    name: '沖縄県',
  },
]

class PrefectureMaster extends Master {
  constructor() {
    super(PREFECTURE)
  }
}

export const Prefecture = new PrefectureMaster()
```

## 解説

`super(PREFECTURE)`で`Master`クラスの`constructor`を呼び出します

```ts
class PrefectureMaster extends Master {
  constructor() {
    super(PREFECTURE)
  }
}
```

# 使い方

https://typeorm.io/#/entities/column-options

https://tech.bitbank.cc/typeorm-entity-guideline/

```ts
transformer: {
  // DBから取得する際は都道府県名を返す
  from(id: number): IMaster {
    return Prefecture.findNameById(id)
  },
  // DBに登録する場合はIDを登録する
  to(value: IMaster): number {
    return value.id
  },
},
```

```ts:sample.
@Entity('contractors')
export class Contractor {
  @Column('tinyint', {
    unsigned: true,
    comment: '都道府県ID',
    transformer: {
      from(id: number): IMaster {
        return Prefecture.findNameById(id)
      },
      to(value: IMaster): number {
        return value.id
      },
    },
  })
  prefecture_id: IMaster
}

```