You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 16:54:21