【发布时间】:2019-10-20 18:38:35
【问题描述】:
我在构建我正在从事的项目时偶然发现了循环依赖问题:一个小型 ORM,用于学习目的。
可以找到重现问题的最小项目here。这是一个更简单的概述:
文章:
import { ManyToMany } from './ManyToMany';
import { Tag } from './Tag';
export class Article {
@ManyToMany(Tag)
tags: Tag[] = [];
}
多对多:
//no imports
export function ManyToMany(entity) {
…
}
标签:
import { ManyToMany } from './ManyToMany';
import { Article } from './Article';
export class Tag {
@ManyToMany(Article)
articles: Article[] = [];
}
重要的是不要对代码进行太多更改或根本不更改,因为这会影响 DX。我不希望这个库的用户创建额外的 hacky 文件来解决这个问题。
我找到了一个讨论列表,但没有一个是优雅的:
- https://medium.com/visual-development/how-to-fix-nasty-circular-dependency-issues-once-and-for-all-in-javascript-typescript-a04c987cf0de
- https://github.com/Microsoft/TypeScript/issues/20361
- Circular Type References in TypeScript
- https://spin.atomicobject.com/2018/06/25/circular-dependencies-javascript/
我能找到的最佳解决方案是使用内部模块模式。此解决方案和所有其他解决方案只是针对此问题的技巧和解决方法,并没有真正解决它。
在不创建额外文件或移动代码的情况下,有没有更好、更优雅的解决方案?
【问题讨论】:
-
你如何使用这些导入?
-
问题是你的
ManyToMany装饰器被传递了一个值,即类对象本身。你需要它来接受一个类型,但我不知道这怎么可能。 -
或者你不应该让它接受一个参数,而是让它内省它被调用的属性的类型声明?不幸的是,我不知道这在 TypeScript 中是否可行,但这将是理想的解决方案。
-
一个肯定可行的解决方案是使引用变得惰性,即传递一个返回实体的函数并且不立即评估它(在属性装饰期间),但稍后当所有模块加载时,类已初始化,并正在创建第一个实例:
@ManyToMany(() => Tag) -
我尝试了延迟加载,但它不起作用stackoverflow.com/questions/63953101/…
标签: javascript typescript decorator circular-dependency typescript-decorator