Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot access variable before initialization error when variable is initialized in another file

I have something like this:

photo.ts

import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from "typeorm"
import { User } from "./User"

@Entity()
export class Photo {
    @PrimaryGeneratedColumn()
    id: number

    @Column()
    url: string

    @ManyToOne(() => User, (user) => user.photos)
    user: User
}

user.ts

import { Entity, PrimaryGeneratedColumn, Column, OneToMany } from "typeorm"
import { Photo } from "./Photo"

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

    @Column()
    name: string

    @OneToMany(() => Photo, (photo) => photo.user)
    photos: Photo[]
}

Am running using nodemon and i have ts-node installed, but am getting the following error:

ReferenceError: Cannot access 'User' before initialization
    at file:///path/to/project/src/database/entities/photo.ts:14:9
    at ModuleJob.run (node:internal/modules/esm/module_job:194:25)

This error beats me as I don't even know where to start because, frankly, I have never encountered the error before, any help would be greatly appreciated.

Versions:

node: v18.17.1
ts-node: v10.9.1
nodemon: v3.0.1
typescript: v5.2.2
like image 486
lulliezy Avatar asked Aug 31 '25 01:08

lulliezy


1 Answers

The problem is that your two modules have a cyclic relationship and they both try to use the other's exported member during the initial module execution. So one or the other has to be run first (photo.ts in your example) and when it tries to use User, that exported member hasn't been initialized yet because user.ts hasn't been executed yet. I have to admit I'm slightly surprised you're getting this as a runtime error because the only place I see them being used in a cycle at the top level of the module code is in the types being applied to user and photos. Perhaps it has something to do with what the decorators are doing, or to the fact that User and Photo are both types and values (constructor functions).

The TypeORM website talks about "circular relationships" here. It says to use the Relation type to avoid this (so user: Relation<User> rather than user: User, and photos: Relation<Photo[]> rather than photos: Photo[]). Apparently this prevents the cycle from arising.

like image 86
T.J. Crowder Avatar answered Sep 02 '25 15:09

T.J. Crowder