仕事でJestを使っているのですが、テストに合計5分以上かかるようになってきました。
そこでテストの時間を短縮するために「swc」というRust製のトランスパイラを使うことにしました。
ただ、swcとTypeORM(というか中で使われているデコレータ周り)の相性が悪いらしく、普通に導入しただけでは動きませんでした。
そこで色々四苦八苦した結果、「これをやったら動くようになったよ」というのをメモしておきたいと思います。
- バージョンメモ
├── @swc/[email protected]
├── [email protected]
├── [email protected]
├── [email protected]
└── [email protected]
entityの中で独自の型を使う場合は、@Column({ type: “varchar” })みたいにカラムのtypeを指定するようにする
結論から書くと、以下ではダメで、
❌Bad
type Gender = "MAN" | "WOMAN";
@Entity()
export class User {
@Column({ unique: true, primary: true })
readonly id: string;
@Column()
name: string;
@Column()
age: string;
@Column() 👈👈👈👈👈👈👈ここがダメ
gender: Gender;
@CreateDateColumn()
readonly createdAt: Date;
}
以下のように書くと、1つのエラーを解消できました。
✅Good
type Gender = "MAN" | "WOMAN";
@Entity()
export class User {
@Column({ unique: true, primary: true })
readonly id: string;
@Column()
name: string;
@Column()
age: string;
@Column({ type: "varchar" }) 👈👈👈👈👈👈こうすると良い
gender: Gender;
@CreateDateColumn()
readonly createdAt: Date;
}
よくわかっていないのですが、Entityの中でプリミティブ型じゃない独自の型を使用していると、型をうまく解決できずに全部undefinedになるらしいです。
(これはswc、reflect-metadata、TypeORMというパッケージいずれかの問題ぽいですがよく分かってません。。)
結果、TypeORMがundefinedを許してくれないのでエラーになるらしいので
undefinedになるかもしれないカラムに、こういうデータ型でカラムを作ってくれという指示をしておくと、undefinedでも通るようになる・・・みたいな感じぽいです。
②リレーションの()=>エンティティ名, (エンティティ)=>エンティティ.カラム名 みたいな書き方をやめて、文字列を直接書くようにする
結論から書くと、以下ではダメで、
❌Bad
type Gender = "MAN" | "WOMAN";
@Entity()
export class User {
@Column({ unique: true, primary: true })
readonly id: string;
@Column()
name: string;
@Column()
age: string;
@Column({ type: "varchar" })
gender: Gender;
@CreateDateColumn()
readonly createdAt: Date;
@OneToMany(() => Post, (Post) => Post.createdBy) 👈👈👈👈👈ここがダメ
posts: Post[];
}
@Entity()
export class Post {
@Column({ unique: true, primary: true })
readonly id: string;
@Column()
title: string;
@Column()
content: string;
@CreateDateColumn()
readonly createdAt: Date;
@ManyToOne(() => User, (User) => User.posts) 👈👈👈👈👈ここがダメ
createdBy: User;
}
以下のように書くと、1つのエラーを解消できました。
✅Good
type Gender = "MAN" | "WOMAN";
@Entity()
export class User {
@Column({ unique: true, primary: true })
readonly id: string;
@Column()
name: string;
@Column()
age: string;
@Column({ type: "varchar" })
gender: Gender;
@CreateDateColumn()
readonly createdAt: Date;
@OneToMany("Post", "createdBy") 👈👈👈👈👈こうすると良いらしい
posts: Post[];
}
@Entity()
export class Post {
@Column({ unique: true, primary: true })
readonly id: string;
@Column()
title: string;
@Column()
content: string;
@CreateDateColumn()
readonly createdAt: Date;
@ManyToOne("User", "posts") 👈👈👈👈👈👈こうすると良いらしい
createdBy: User;
}
よくわかっていないのですが、swcはファイルを1つずつトランスパイルをしていく(?)ので、循環参照が起こる書き方をしていると「循環参照してんぞ」なエラー(before initializeみたいなエラー)が出ちゃうらしい。
なので循環参照しないような書き方でリレーションを書くようにします。
そのための書き方が用意されてるぽかったので、これで書きなおしたらエラーが出なくなりました↓。
https://github.com/typeorm/typeorm/issues/4190
そんな感じでした。
おわり
コメント