Búsqueda de sitios web

typescript - TypeORM OneToMany causa "ReferenceError: Cannot access '' before initialization"


Tengo dos entidades: Usuario y Hábito. Un usuario puede crear múltiples Hábitos, por lo tanto utilizo una relación UnoAMuchos en el Usuario (y MuchosAUno en el Hábito, respectivamente).

Entidad de Usuario

import {Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, BeforeInsert, BeforeUpdate, OneToMany} from "typeorm";
import * as bcrypt from "bcryptjs";
import { Habit } from "../habits/habits.entity";

@Entity()
export class User {
    @PrimaryGeneratedColumn("uuid")
    id: string;

    @Column()
    name: string;

    @Column()
    email: string;

    @Column()
    password: string;

    @OneToMany(type => Habit, habit => habit.author)
    habits: Habit[];

    @CreateDateColumn()
    dateCreated: Date;

    @UpdateDateColumn()
    dateUpdated: Date;

    @BeforeInsert()
    @BeforeUpdate()
    async hashPassword(): Promise<void> {
        this.password = await bcrypt.hash(this.password,10);
    }

    async comparePassword(password: string): Promise<boolean> {
        return bcrypt.compare(password, this.password);
    }

    constructor(props: any) {
        Object.assign(this, props);
    }
}

Entidad de hábito

import {Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn, ManyToOne} from "typeorm";
import { User } from "../users/users.entity";

@Entity()
export class Habit {
    @PrimaryGeneratedColumn("uuid")
    id: string;

    @Column()
    name: string;

    @Column({ nullable: true})
    description?: string;

    @ManyToOne(type => User, user => user.habits)
    author: User;

    @CreateDateColumn()
    dateCreated: Date;

    @UpdateDateColumn()
    dateUpdated: Date;

    constructor(props: Partial<Habit>) {
        Object.assign(this, props);
    }
}

Problema

Al configurar la relación anterior recibo el siguiente error

WARNING in Circular dependency detected:
apps\api\src\habits\habits.entity.ts -> apps\api\src\users\users.entity.ts -> apps\api\src\habits\habits.entity.ts

WARNING in Circular dependency detected:
apps\api\src\users\users.entity.ts -> apps\api\src\habits\habits.entity.ts -> apps\api\src\users\users.entity.ts


/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "User", function() { return User; });
                                                                                               ^
ReferenceError: Cannot access 'User' before initialization
    at Module.User (...\dist\apps\api\main.js:1782:96)
    at Module../apps/api/src/habits/habits.entity.ts (...\dist\apps\api\webpack:\apps\api\src\habits\habits.entity.ts:42:13)
    at __webpack_require__ (...\dist\apps\api\webpack:\webpack\bootstrap:19:1)
    at Module../apps/api/src/users/users.entity.ts (...\dist\apps\api\main.js:1790:79)
    at __webpack_require__ (...\dist\apps\api\webpack:\webpack\bootstrap:19:1)
    at Module../apps/api/src/config/db-config.service.ts (...\dist\apps\api\main.js:1038:77)
    at __webpack_require__ (...\dist\apps\api\webpack:\webpack\bootstrap:19:1)
    at Module../apps/api/src/config/config.module.ts (...\dist\apps\api\main.js:978:76)
    at __webpack_require__ (...\dist\apps\api\webpack:\webpack\bootstrap:19:1)
    at Module../apps/api/src/app/app.module.ts (...\dist\apps\api\main.js:147:79)

Nota

Uso Nx y he creado una aplicación NestJS. La versión de TypeOrm es "^0.2.22" y la versión de @nestjs/typeorm es "^6.2.0"

Mi tsconfig es el siguiente:

{
  "compileOnSave": false,
  "compilerOptions": {
    "rootDir": ".",
    "sourceMap": true,
    "declaration": false,
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "importHelpers": true,
    "target": "es2015",
    "module": "esnext",
    "typeRoots": ["node_modules/@types"],
    "lib": ["es2018", "dom"],
    "skipLibCheck": true,
    "skipDefaultLibCheck": true,
    "baseUrl": ".",
    "paths": {
      "@awhile/contracts": ["libs/contracts/src/index.ts"],
      "@awhile/ui": ["libs/ui/src/index.ts"]
    }
  },
  "exclude": ["node_modules", "tmp"]
}

He intentado usar una relación ManyToMany y funcionó. Además, en una aplicación NestJS separada (sin Nx) no puedo reproducir este error de referencia. Cambiar la versión de target de ECMAScript en el tsconfig.json tampoco funcionó.

Ambas entidades solo se utilizan en sus servicios y no se instancian en ningún otro lugar.

Agradezco cualquier ayuda. Gracias de antemano.

Respuesta #1

Utiliza el contenedor de tipo Relation para evitar problemas de dependencia circular, como se describe aquí.

Por ejemplo:

import {Entity, OneToMany, Relation} from "typeorm";
import {Habit} from "../habits/habits.entity";

@Entity()
export class User {
    ...

    @OneToMany(type => Habit, habit => habit.author)
    habits: Relation<Habit>[];

    ...
}

Respuesta #2

En tsconfig, configurar el objetivo a "esnext" y el módulo a "commonjs" solucionó el problema para mí

{
  "extends": "../../tsconfig.json",
  "compilerOptions": {
    "types": ["node", "jest"],
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "module": "commonjs",
    "target": "esnext"
  },
  "include": ["**/*.ts"]
}

Artículos relacionados