TypeORMはTypeScriptで使えるORM。
すごくニッチなニーズな気もするが、simple-arrayというTypeORM特有の型をコード中で扱う際に、numberの配列として扱いたい。
simple-array
配列をDBに手軽にストアしたいなら便利。ただしDocに明記されていない問題が一つ。
string要素以外格納できない。
より厳密に言うと、string以外の要素を含んだ配列を渡すと、DBから値を取得する際にstringとして返ってくる。
ex) [1, 2, 3] -> DB -> ['1', '2', '3']
@Column({ type: 'simple-array' })
public elements: number[]
のように定義していても上記のような動作をするので、普通に嫌だ。
https://github.com/typeorm/typeorm/issues/1092
https://github.com/typeorm/typeorm/issues/2267
この辺を見ても分かるが、TypeORM側としてはライブラリサポートする気はなさそう。
どうするか
これで解決できた。
@Column({ type: 'simple-array', nullable: true })
public elements: number[]
/**
 * @NOTE: simple-array type automatically save column as string.
 * numifyElements will fix string elements to number after each time entity is loaded.
*/
@AfterLoad()
numifyElements() {
  if (this.elements&& this.elements.length) {
    this.elements.forEach((e, i, self) => self[i] = parseInt(String(e), 10))
  }
}
@AfterLoadデコレータがついた関数を定義しておくと、Entityがロードされる度に所定の処理を行うことができる。
simple-arrayは少なくとも配列の状態でロードしてくれるので、その要素を自分が求める型に変換する。
カラム定義はnumber[]にしておかないとコード内で型について怒られる。
ただし、そうすることによってnumifyElements内のparseInt(String(id), 10)でわざわざidをStringで囲う必要が出てくる。
なぜなら既にnumberと定義されているものをparseIntに渡すので、tsに怒られてしまうから。
そもそもnumber[]と定義しているにも関わらず、なぜstring[]を入れることができているのかについてはよくわからない。
そのうちちゃんと調べよう。