TypeORM の date 型のカラムは Date ではなく string
ほんとにあった怖い話...🥶🥶🥶
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();
birthday
は Date
として定義しているので、当然 toISOString() も問題なく使用できるものと思っていました。
ところが、いざ実行してみると...
TypeError: user.birthday.toISOString is not a function
というエラーがエラーが発生していました。
デバッグして、型を確認すると string
であることが判明!
文字列で toISOString()
が実行できるはずもありません。
エラーが起きて当然です...😇
date は string にマッピングされる
Date
ではなく、string
は仕様で、意図した動作であるようです。
以下の issue の中で、やり取りがされていました。
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オブジェクトにマップされます。私たちは過去に日付の振る舞いについて多くの議論をしました。
つまり、最初の Entity
は以下のように定義するのが正しいと言えるでしょう。
@Entity('users')
export class User extends BaseEntity {
@Column({ name: "name" })
public name: string;
@Column({ name: "birthday", type: "date" })
public birthday: string; // Date ではなく string
}
まとめ
実行するまで気付けないエラーって...
怖いなぁ 怖いなぁ...
Discussion