TypeORM中Student与Teacher双向多对多关系定义报错求助
解决TypeORM多对多关联与rollup-plugin-dts编译错误问题
问题场景
现有EntityBase抽象类:
import { PrimaryGeneratedColumn, Column } from "typeorm" /* * 使用Data Mapper模式 */ export abstract class EntityBase { @PrimaryGeneratedColumn() public id: number @Column() public created: Date @Column() public modified: Date }
尝试在Student和Teacher实体间建立多对多关联,分别定义两个实体后,执行编译时出现错误。
Student实体代码
import { Entity, Column, ManyToMany, JoinTable } from "typeorm" import { EntityBase } from "./EntityBase" import { Teacher } from "./Teacher" @Entity() export class Student extends EntityBase { @Column() public firstName: string @Column() public lastName: string @Column({ unique: true }) public email: string @Column() public isSuspended: boolean @ManyToMany(() => Teacher, (teacher) => teacher.students) @JoinTable() public teachers: Teacher[] constructor(first: string, last: string, email: string, isSuspended?: boolean) { super(); this.firstName = first; this.lastName = last; this.email = email; this.isSuspended = isSuspended ?? false; this.teachers = []; } }
Teacher实体代码
import { Entity, Column, JoinTable, ManyToMany } from "typeorm" import { EntityBase } from "./EntityBase" import { Student } from "./Student" @Entity() export class Teacher extends EntityBase { @Column() public firstName: string @Column() public lastName: string @Column({ unique: true }) public email: string @ManyToMany(() => Student, (student) => student.teachers) @JoinTable() public students: Student[] constructor(first: string, last: string, email: string) { super(); this.firstName = first; this.lastName = last; this.email = email; this.students = []; } }
编译错误信息
build/index.d.ts → build/index.d.ts... [!] (plugin dts) Error: Syntax not yet supported 2 | import { EntityBase } from "./EntityBase" 3 | import { Student } from "./Student" > 4 | declare @Entity() | ^^^^^^^ 5 | class Teacher extends EntityBase { 6 | @Column() 7 | public firstName: string Domain/Entities/Teacher.ts Error: Syntax not yet supported 2 | import { EntityBase } from "./EntityBase" 3 | import { Student } from "./Student" > 4 | declare @Entity() | ^^^^^^^ 5 | class Teacher extends EntityBase { 6 | @Column() 7 | public firstName: string at Transformer.convertStatement (/usr/src/Node.JSRestAPI/node_modules/rollup-plugin-dts/dist/rollup-plugin-dts.cjs:1248:19) at new Transformer (/usr/src/Node.JSRestAPI/node_modules/rollup-plugin-dts/dist/rollup-plugin-dts.cjs:1177:18) at convert (/usr/src/Node.JSRestAPI/node_modules/rollup-plugin-dts/dist/rollup-plugin-dts.cjs:1168:25) at Object.transform (/usr/src/Node.JSRestAPI/node_modules/rollup-plugin-dts/dist/rollup-plugin-dts.cjs:1484:31) at transformFile (/usr/src/Node.JSRestAPI/node_modules/rollup-plugin-dts/dist/rollup-plugin-dts.cjs:1588:50) at Object.transform (/usr/src/Node.JSRestAPI/node_modules/rollup-plugin-dts/dist/rollup-plugin-dts.cjs:1601:24) at /usr/src/Node.JSRestAPI/node_modules/rollup/dist/shared/rollup.js:22840:40 npm ERR! Lifecycle script `rollup` failed with error: npm ERR! Error: command failed npm ERR! in workspace: core@1.0.0 npm ERR! at location: /usr/src/Node.JSRestAPI/src/core npm ERR! Lifecycle script `build` failed with error: npm ERR! Error: command failed npm ERR! in workspace: core@1.0.0 npm ERR! at location: /usr/src/Node.JSRestAPI/src core
解决方案
1. 修正多对多关联定义
TypeORM的多对多关联仅需在任意一方添加@JoinTable()装饰器,两边同时添加会导致重复逻辑,干扰类型声明生成。移除其中一方的@JoinTable即可。
2. 解决循环引用问题
使用TypeScript的类型导入(import type)替代普通导入,避免运行时的循环引用,同时让rollup-plugin-dts能正确处理类型声明。
修正后的实体代码
Student实体(保留@JoinTable)
import { Entity, Column, ManyToMany, JoinTable } from "typeorm" import { EntityBase } from "./EntityBase" // 类型导入仅用于类型检查,不会引入运行时依赖 import type { Teacher } from "./Teacher" @Entity() export class Student extends EntityBase { @Column() public firstName: string @Column() public lastName: string @Column({ unique: true }) public email: string @Column() public isSuspended: boolean @ManyToMany(() => Teacher, (teacher) => teacher.students) // 可选:自定义关联表名称和字段,提升可读性 @JoinTable({ name: "student_teacher", joinColumns: [{ name: "student_id", referencedColumnName: "id" }], inverseJoinColumns: [{ name: "teacher_id", referencedColumnName: "id" }] }) public teachers: Teacher[] constructor(first: string, last: string, email: string, isSuspended?: boolean) { super(); this.firstName = first; this.lastName = last; this.email = email; this.isSuspended = isSuspended ?? false; this.teachers = []; } }
Teacher实体(移除@JoinTable)
import { Entity, Column, ManyToMany } from "typeorm" import { EntityBase } from "./EntityBase" // 类型导入避免运行时循环引用 import type { Student } from "./Student" @Entity() export class Teacher extends EntityBase { @Column() public firstName: string @Column() public lastName: string @Column({ unique: true }) public email: string @ManyToMany(() => Student, (student) => student.teachers) public students: Student[] constructor(first: string, last: string, email: string) { super(); this.firstName = first; this.lastName = last; this.email = email; this.students = []; } }
额外编译优化
如果仍存在类型声明编译问题,可以调整构建流程:
- 在
tsconfig.json中启用"declaration": true,让TypeScript自动生成.d.ts文件 - 替换
rollup-plugin-dts为@rollup/plugin-typescript,直接由TypeScript处理类型声明生成
内容的提问来源于stack exchange,提问作者khteh
相关产品推荐
相关产品推荐

