typescriptnestjsrelational-databasetypeormnestjs-typeorm

Circular Dependency error in NestJS TypeORM Relations with Entity Decorator


Why do I get this circular dependency error in NestJS TypeORM Relations with Entity Decorator when setting up a OneToMany and ManyToOne relation between User and Item?

cannot access User before initialization

NestJS version: 11.0.1

Full Source Code Repository: https://github.com/catc0de1/myex-backend

user.entity:

import {
  AfterInsert,
  Entity,
  Column,
  PrimaryGeneratedColumn,
  AfterUpdate,
  AfterRemove,
  OneToMany,
} from 'typeorm';
import { Item } from '@items/item.entity';

@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string;

  @Column({ unique: true })
  email: string;

  @Column()
  password: string;

  @OneToMany(() => Item, (item) => item.user)
  items: Item[];

  @AfterInsert()
  logInsert() {
    console.log(`User with ID ${this.id} has been inserted.`);
  }

  @AfterUpdate()
  logUpdate() {
    console.log(`User with ID ${this.id} has been updated.`);
  }

  @AfterRemove()
  logRemove() {
    console.log(`User with ID ${this.id} has been removed.`);
  }
}

item.entity:

import { Entity, Column, PrimaryGeneratedColumn, ManyToOne } from 'typeorm';
import { User } from '@users/user.entity';

@Entity()
export class Item {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string;

  @Column()
  description: string;

  @Column()
  price: number;

  @Column()
  location: string;

  @Column()
  category: string;

  @ManyToOne(() => User, (user) => user.items, { nullable: false })
  user: User;
}

Error log:

⠋  TSC  Initializing type checker.../home/zul/vsc/nest/myex/src/users/user.entity.ts:12
export class User {
             ^

ReferenceError: Cannot access 'User' before initialization
    at Object.User (/home/zul/vsc/nest/myex/src/users/user.entity.ts:12:14)
    at Object.<anonymous> (/home/zul/vsc/nest/myex/src/items/item.entity.ts:23:60)
    at Module._compile (node:internal/modules/cjs/loader:1738:14)
    at Object..js (node:internal/modules/cjs/loader:1871:10)
    at Module.load (node:internal/modules/cjs/loader:1470:32)
    at Module._load (node:internal/modules/cjs/loader:1290:12)
    at TracingChannel.traceSync (node:diagnostics_channel:322:14)
    at wrapModuleLoad (node:internal/modules/cjs/loader:238:24)
    at Module.require (node:internal/modules/cjs/loader:1493:12)
    at require (node:internal/modules/helpers:152:16)

Solution

  • This error happens because a relation property can be either the entity or a lazy Promise of that entity depending on your setup. TypeORM provides a helper type that covers both cases and keeps your types consistent.

    import { User } from '@users/user.entity';
    import type { Relation } from 'typeorm';
    
    @Entity()
    export class Item {
        ...
    
        @ManyToOne(() => User, (user) => user.items, { nullable: false })
        user: Relation<User>; // <-- wrap your entity with the helper type 
    }
    

    Hope this helps!