Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with generated code on circular dependency #42

Open
kelvien opened this issue Nov 30, 2020 · 11 comments
Open

Issue with generated code on circular dependency #42

kelvien opened this issue Nov 30, 2020 · 11 comments
Assignees
Labels
bug Something isn't working

Comments

@kelvien
Copy link

kelvien commented Nov 30, 2020

Issue
It seems like the generated code through this Babel plugin raises an issue in using a variable before it is initialized.

let User = ...
_dec9 = Reflect.metadata("design:type", typeof Profile === "undefined" ? Object : Profile)
...

let Profile = ...
_dec9 = Reflect.metadata("design:type", typeof User === "undefined" ? Object : User)

I did see the same issue reported by someone here - https://stackoverflow.com/questions/61297622/typescript-metadata-reflection-references-other-classes-before-they-are-defined, but I don't think it's closed with a solution to the core problem.

Context
I'm using TypeORM for my interaction with a database. And in this example I defined two entities that need each other (a one-to-one relationship)
I provide a minimal reproduction code in this repo - https://github.com/kelvien/repro-next-circ-metadata/

It seems like you've mentioned this as one of the pitfalls. I'm just wondering if there is an alternate way in solving this issue, and perhaps a longer term solution to this.

@leonardfactory
Copy link
Owner

Usually in TypeORM you can simply use @OneToOne(type => Entity) instead of @OneToOne(Entity) to resolve the circular dependency which is unsupported directly in JS. Have you tried this way?

@kelvien
Copy link
Author

kelvien commented Nov 30, 2020

Do you mean passing the string instead of the function, right? Suggested here - typeorm/typeorm#4190
I tried that too and it didn't work. Here is the generated code:

_dec4 = Object(typeorm["OneToOne"])('User'), _dec5 = Reflect.metadata("design:type", typeof User === "undefined" ? Object : User)

The relationship is referenced by string, but the Reflect.metadata is doing that typeof check with the class that does not exist yet.

@leonardfactory
Copy link
Owner

Didn't know about the string version, however the problem here is in the type definition (user: User;) not the relationship definition (@OneToOne('User', 'user'))

I may suggest to type user: User; as user: User | undefined;. This should relax the type definition

@kelvien
Copy link
Author

kelvien commented Nov 30, 2020

I gave that a try, but the generated code doesn't change at all
Code:

  @OneToOne('Profile')
  profile?: Profile | undefined;

Transpiled code

_dec9 = Reflect.metadata("design:type", typeof Profile === "undefined" ? Object : Profile

@kelvien
Copy link
Author

kelvien commented Nov 30, 2020

Changing it to Profile | null also generate the same code.
But profile?: Profile | string results into _dec26 = Reflect.metadata("design:type", Object), obviously not what I wanted but at least has less stricter type check

@kelvien
Copy link
Author

kelvien commented Dec 2, 2020

Update: I also notice that my Babel/Webpack is outputting a different result between dev and prod. And it seems like it works fine if Webpack bundles my barrel file correctly (a rollup index file for all of my db models). I put more details of my question here - https://stackoverflow.com/questions/65102724/inconsistent-webpack-with-babel-output-in-using-a-barrel-file-between-dev-and-pr

@mmahalwy
Copy link

mmahalwy commented Feb 3, 2021

@kelvien any luck with this? I see you're using nextjs too

@kelvien
Copy link
Author

kelvien commented Feb 3, 2021

Hey @mmahalwy, one alternative was to put the models with circular dependency into one file, it's not the most ideal approach, but I can't seem to find a better solution other than fixing the transpiler itself.

@mmahalwy
Copy link

mmahalwy commented Feb 3, 2021

@kelvien oh yeah, but that could get really messy really quickly 😓

@MatthieuCoelho
Copy link

Got the same issue with nextjs, still no solution ? =(

@leonardfactory leonardfactory added the bug Something isn't working label Mar 18, 2021
@leonardfactory
Copy link
Owner

Probably TypeScript is smarter here while generating decorators and is wrapping them in functions. I'll see if this is solvable using this plugin alone, or if the problem arises from babel decorators generation process

@leonardfactory leonardfactory self-assigned this Mar 18, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants