在另一个文件中初始化变量时,无法在初始化错误之前访问变量

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

提问人:lulliezy 提问时间:10/9/2023 最后编辑:derpirscherlulliezy 更新时间:10/9/2023 访问量:107

问:

我有这样的东西:

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[]
}

正在运行,并且我已经安装,但收到以下错误:nodemonts-node

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)

这个错误打败了我,因为我甚至不知道从哪里开始,因为坦率地说,我以前从未遇到过这个错误,任何帮助将不胜感激。

版本:

node: v18.17.1
ts-node: v10.9.1
nodemon: v3.0.1
typescript: v5.2.2
节点 .js 打字稿 类型 nodemon ts-node

评论

0赞 T.J. Crowder 10/9/2023
我没有适合您的(特定)解决方案,但问题是您的两个模块具有循环关系,并且它们都尝试在初始模块执行期间使用另一个导出的成员(感谢装饰器)。因此,必须首先运行一个或另一个(在您的示例中),并且当它尝试使用 时,导出的成员尚未初始化,因为尚未执行。一般的解决方案是避免在初始执行期间每个模块尝试使用另一个模块导出的成员的循环。但我不知道怎么回事......photo.tsUseruser.ts
0赞 T.J. Crowder 10/9/2023
...你可以用上面的装饰器来做到这一点。通常,您必须延迟其中一个类的初始化,直到另一个类准备就绪。我可以想出一种笨拙的方法来做到这一点,但你必须选择是否这样做,或者这个选择取决于其他模块如何使用它们。UserPhoto
1赞 T.J. Crowder 10/9/2023
需要明确的是:模块之间有循环关系是可以的,ESM 就是为了处理这个问题而设计的。问题在于,当每个模块中的顶级代码依赖于另一个已经运行的模块的顶级代码时。在非循环关系中,JavaScript 引擎可以按适当的顺序执行模块,但在循环关系中,它是 Catch-22。
0赞 T.J. Crowder 10/9/2023
TypeORM网站上关于“循环关系”的一些信息在这里: typeorm.io/#relations-in-esm-projects 它说使用类型来避免这种情况。我不清楚这有什么帮助,但我从未使用过 TypeORM,也没有深入研究过它,所以......Relation
1赞 lulliezy 10/9/2023
@T.J.Crowder它确实有效,你可以输入答案,所以我接受它,非常感谢

答:

0赞 T.J. Crowder #1

问题在于,您的两个模块具有循环关系,并且它们都尝试在初始模块执行期间使用另一个导出的成员。因此,必须首先运行一个或另一个(在您的示例中),并且当它尝试使用 时,导出的成员尚未初始化,因为尚未执行。我不得不承认,我有点惊讶你把它作为一个运行时错误,因为我看到它们在模块代码顶层的循环中被使用的唯一地方是在应用于 和 的类型中。也许这与装饰器正在做的事情有关,或者与 和 既是类型是值(构造函数)这一事实有关。photo.tsUseruser.tsuserphotosUserPhoto

TypeORM网站在这里谈到了“循环关系”。它说使用类型来避免这种情况(so 而不是 ,而不是 )。显然,这阻止了循环的出现。Relationuser: Relation<User>user: Userphotos: Relation<Photo[]>photos: Photo[]