🥶

TypeORM の date 型のカラムは Date ではなく string

2023/08/28に公開

ほんとにあった怖い話...🥶🥶🥶

TypeORM の date は Date ではなかった

TypeORM で以下のような Entity を定義します。

birthday なので、日付と時刻を表す timestamp ではなく、日付のみを表す date をデータベース上の型としています。

@Entity('users')
export class User extends BaseEntity {
  @Column({ name: "name" })
  public name: string;

  @Column({ name: "birthday", type: "date" })
  public birthday: Date;
}

toISOString() でエラーが発生している!?

Date を文字列に変換したいなぁと思い、以下のような実装をしました。

// user: 上記 User クラス
const birthdayString = user.birthday.toISOString();

birthdayDate として定義しているので、当然 toISOString() も問題なく使用できるものと思っていました。

ところが、いざ実行してみると...

TypeError: user.birthday.toISOString is not a function

というエラーがエラーが発生していました。

デバッグして、型を確認すると string であることが判明!

文字列で toISOString() が実行できるはずもありません。

エラーが起きて当然です...😇

date は string にマッピングされる

Date ではなく、string は仕様で、意図した動作であるようです。

以下の issue の中で、やり取りがされていました。

https://github.com/typeorm/typeorm/issues/2176

TypeORM の開発メンバーの回答です。

its expected behaviour. date is mapped into string since it causes lot of issues when its mapped into Date because of missing hours minutes and seconds. Only full datetime is mapped into Date object. We had lot of discussions about dates behaviour in past.

時分秒が欠落するため、Dateにマッピングすると多くの問題が発生するためです。完全なdatetimeのみがDateオブジェクトにマップされます。私たちは過去に日付の振る舞いについて多くの議論をしました。

DeepLで翻訳

つまり、最初の Entity は以下のように定義するのが正しいと言えるでしょう。

@Entity('users')
export class User extends BaseEntity {
  @Column({ name: "name" })
  public name: string;

  @Column({ name: "birthday", type: "date" })
  public birthday: string; // Date ではなく string
}

まとめ

実行するまで気付けないエラーって...

怖いなぁ 怖いなぁ...

参考

コラボスタイル Developers

Discussion