TypeScriptでESNextを使う場合のSequelizeの書き方
TypeScriptでSequelizeを使おうとして、マニュアル(Manual | Sequelize)にある通りに、null assertionを使ってモデルのフィールドを定義してやると、うまく動かなかった。
import { DATEONLY, INTEGER, STRING, Model, Sequelize } from "sequelize"; export const sequelize = new Sequelize("sqlite::memory:"); export class User extends Model { id!: number; name!: string; birth!: string; } User.init({ id: { type: INTEGER, primaryKey: true, autoIncrement: true, }, name: { type: STRING, allowNull: false, }, birth: { type: DATEONLY, allowNull: false, } }, { sequelize } ); export async function main() { await sequelize.sync({ force: true }); const user = await User.create({ name: "Albert Einstein", birth: "1879-03-14" }); console.log(user.name, user.birth); } main();
コンパイラオプションのターゲットがESNextに設定されている場合、上のコードを実行すると undefined undefined
と出力される。これは、最新版のTypeScriptが TC39 Stage 3 提案のクラスフィールド に対応しており、ターゲットがESNextになっている場合は、useDefineForClassFields
コンパイラオプションが有効になって、現行の意味論である「定義」意味論が使われるからだ。(「定義」意味論については、Babelプラグインの順序とallowDeclareFieldsの妙を参照してほしい。)
この問題は、以下のいずれかで解決する:
useDefineForClassFields
オプションをfalse
に設定する。- null assertion の代わりに
declare
プロパティ修飾子を使う。
export class User extends Model { declare id: number; declare name: string; declare birth: string; }
新規のコードを書くときは declare
修飾子を使うようにした方がいいだろう。