-
-
Notifications
You must be signed in to change notification settings - Fork 81
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
Circular dependencies between models #45
Comments
+1, in my (complicated enough) domain models generated models are useless because of circular dependencies. |
Against the comment in https://github.com/mobxjs/mst-gql/blob/master/generator/generate.js#L354, types.late isn't enough to prevent circular dependencies :) |
@chrisdrackett does editing the generated file solve your problems? (I realise this isn't a long term fix). @Amareis is the problem with TS types or a JS issue? |
@elie222 just TS typings. For correct circular references handling we need to use |
https://github.com/pahen/madge can be helpful in find and resoving circular deps. My current models have 36 of it. |
@elie222 editing the generated file does fix the problem, but like @Amareis mentioned because this makes the return type I can try and add a note about this if needed to the docs. Its really more a MST thing than a mst-gql thing, but might be worth letting users know about regardless. |
So I'm thinking we can handle this by manually generating the TS types. TS shouldn't have issues with the circular dependencies in general. For example, the following code compiles fine: interface Post {
id: string
comment?: Comment
}
interface Comment {
id: string
post: Post
}
const post: Post = {
id: 'a',
comment: {
id: 'b',
post: {
id: 'c',
}
}
} Having TS figure out the types from the model itself is nice usually, but as we're generating this code in any case, we may as well generate the TS types too and get around this circular any issue. @mweststrate I know you've dealt with circular dependencies quite a lot. What are your thoughts on this? |
Yep, that's will really cool! Besides of circular deps handling, it'll make nice typenames in compiler errors, instead of usual mst types garbage. |
I think it is a really cool idea! Be aware to use interfaces instead of
types wherever possible, as types in TS can't have circular refs either
…On Fri, Jul 12, 2019 at 12:30 PM Иван Плесских ***@***.***> wrote:
Yep, that's will really cool! Besides of circular deps handling, it'll
make nice typenames in compiler errors, instead of usual mst types garbage.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#45?email_source=notifications&email_token=AAN4NBGSB3PNVX6PFMYTPELP7BMM5A5CNFSM4H4LOAR2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODZZMGMQ#issuecomment-510837554>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAN4NBELEH6JNRCBMW6UNCLP7BMM5ANCNFSM4H4LOARQ>
.
|
Regardless on whether the above is implemented or not, in general two tips that help with breaking circular type dependencies:
Hope that helps in the mean time! |
@elie222 have you done any work on this? I was thinking of giving it a try tomorrow and/or over the weekend |
I have not unfortunately :( too busy right now
…On Fri, 26 Jul 2019 at 6:36 Chris Drackett ***@***.***> wrote:
@elie222 <https://github.com/elie222> have you done any work on this? I
was thinking of giving it a try tomorrow and/or over the weekend
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#45?email_source=notifications&email_token=AAXSQXY4A6D2LK2B2346BZ3QBJWMDA5CNFSM4H4LOAR2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD23MU3I#issuecomment-515295853>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAXSQX2KVTMW7PNKDNVOBYTQBJWMDANCNFSM4H4LOARQ>
.
|
#69 should already make this much better |
Wouldn't it be possible to use graphql-codegen (https://graphql-code-generator.com) for this? It can generate TS interfaces for the same graphql schema we use in mst-gql-scaffold.js. |
The MST types are different to what graphql codegen will produce.
But there are places this project could have used graphql codegen. It was
lightly discussed in some another issue.
…On Wed, 4 Sep 2019 at 16:25 beep ***@***.***> wrote:
So I'm thinking we can handle this by manually generating the TS types.
Wouldn't it be possible to use https://graphql-code-generator.com for
this? It can generate TS interfaces for the same graphql schema we use in
mst-gql-scaffold.js.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#45?email_source=notifications&email_token=AAXSQX7CFYPQGIYMEUQKKP3QH6ZNFA5CNFSM4H4LOAR2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD53RW6Q#issuecomment-527899514>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAXSQX3PIHIU3EBEQ2KD3MDQH6ZNFANCNFSM4H4LOARQ>
.
|
@elie222 I see. And how should this MST compatible TS interface look like? Do you have any idea of this? |
Take a look here:
https://github.com/mobxjs/mobx-state-tree#typescript-and-mst
If you're running MST in your project you should be able to hover over
items and see their types.
You can do something like this to get TS types from an MST model in a
regular MST project:
type ISearchStoreType = typeof SearchStore.Type
export interface ISearchStore extends ISearchStoreType {}
…On Wed, 4 Sep 2019 at 17:07, beep ***@***.***> wrote:
@elie222 <https://github.com/elie222> I see. And how should this MST
compatible TS interface look like? Do you have any idea of this?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#45?email_source=notifications&email_token=AAXSQXZGK24BLLKNEIM5EDDQH66KXA5CNFSM4H4LOAR2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD53V7TA#issuecomment-527917004>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAXSQX4JJEO7WWIVX2BRA73QH66KXANCNFSM4H4LOARQ>
.
|
Thanks for these details! Another idea/question: implementing this in the generator as a general mechanism for any late() type: mobxjs/mobx-state-tree#943 (comment) We would then always have the actual prop as of type any (because of IAnyModelType) and a matching view, which returns the prop casted using Instance<...> and would use this view function in code where we want hints from the IDE. This is still hackish but could be an optional workaround until manually generated TS types happen. |
Implements the trick mentioned in this comment: mobxjs/mobx-state-tree#943 (comment) Every late() reference field will be of type IAnyModelType and will be accompanied by a view getter casting it to the actual type of the prop. After this a reference field name "refField" should be accessed as "refFieldProp" which will provide correct typings/autocomplete in IDEs. This trick works up to typescript 3.4.x and doesn't work in 3.5 and above :-( Using Instance<...> like this however still works in all versions: mobxjs/mobx-state-tree#943 (comment) refs mobxjs#45
I implemented this solution above. It works nicely with TS 3.4, but doesn't work with newer versions. |
there seems to be something going on with TS versions past 3.4 that make things like this project and others I use (graphql-nexus/nexus-prisma#291) have issues. I haven't taken the time to dig into it (for now I'm just locked to 3.4.5). |
Is there anyone working on @elie222's proposal about generating TS types "manually"?
|
I haven't touched it all unfortunately.
…On Tue, 24 Sep 2019 at 15:24, beep ***@***.***> wrote:
Is there anyone working on @elie222 <https://github.com/elie222>'s
proposal about generating TS types "manually"?
So I'm thinking we can handle this by manually generating the TS types. TS
shouldn't have issues with the circular dependencies in general. For
example, the following code compiles fine:
interface Post {
id: string
comment?: Comment
}
interface Comment {
id: string
post: Post
}
const post: Post = {
id: 'a',
comment: {
id: 'b',
post: {
id: 'c',
}
}
}
Having TS figure out the types from the model itself is nice usually, but
as we're generating this code in any case, we may as well generate the TS
types too and get around this circular any issue.
@mweststrate <https://github.com/mweststrate> I know you've dealt with
circular dependencies quite a lot. What are your thoughts on this?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#45?email_source=notifications&email_token=AAXSQX2DFIHY6D2ZOCPDOKDQLIBH5A5CNFSM4H4LOAR2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD7OET3A#issuecomment-534530540>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAXSQX4RVIN5LAVR4JKBUNTQLIBH5ANCNFSM4H4LOARQ>
.
|
I may try to implement it, but I don't know what actually needs to be done here. Can you give me some hints how it would work? How these generated TS types would be associated with the MSTGQLObject based MST models the generator generates? If that's how it is planned to work at all - I'm a little bit lost here. |
I think after the types are generated we would just associate them with the return of I think also ideally the user should be able to easily extend these types in case they are adding props, views, actions, etc. to a store themselves. |
@beepsoft would it be helpful for me to attempt to put together example output for some of the examples in this repo? That might give us a target to discuss before we worry about how to get from the input to output. |
@chrisdrackett Yes, an actual example would be a great starting point, thank you! |
I'm a bit swamped to have time to help out so instead I left a $50 bounty on bountysource :-) |
@beepsoft ok, I'll work on it some today. Not sure if I'll get anything to share as I probably need to learn a lot more about how MST types work in general :D |
I went ahead and put together a draft branch for this work here: #110 This was a quick first pass and certainly missing a lot. It also currently does not do any generation. Hopefully this can act as a discussion starter! |
#112 is probably somewhat related |
+1 i have circular deps in gql base file generate at base model field
at the same time custom model required import UserGroupModelBase
as a result -> circular deps + build error |
@beepsoft I've started a new PR that's a bit better #117 . The issue that it solves is that in certain cases the actual import is not yet defined depending on the loading order. By using the internal.js module you get more control over the exact loading order. However, it doesn't solve anything about the circular type declarations preventing proper type inference on models that reference themselves. |
@gadzillllla Can you try with #117 and reorder the |
@RXminuS we tried it, and it works fine for now |
I just tried if it is any better with TS 3.7.0-beta, but unfortunately it is not. |
@RXminuS had the same issue as @gadzillllla, JS codebase with circular dependencies. Tried running your fork and got this error while generating the gql models
mst-gql.config.js module.exports = {
force: true,
format: "js",
input: "app/graphql/schema.graphql",
outDir: "app/frontend/models",
roots: [] // auto-detect
}; |
#128 is generating TS for JS spec: export const RootStoreBase: typeof RootStoreBaseNoRefs = RootStoreBaseNoRefs Also exhibiting the same webpack circular dependencies error while loading app:
|
(@onomated wrong @ in previous message, sorry :-) ) I've never seen such webpack error, sorry, then it is a different issue. |
fixed in |
🎉 Great work @godness84, thanks for your solution and @chrisdrackett for managing the merge! I'm so happy with this issue being solved! |
Thanks to you guys! |
still facing issue with circular deps
using TS 3.7.3 and mst-gql 0.12.0 |
@michaelspeed can you give more details? Does it compile? Does TS understand the types when you put the cursor on? Have you customized the code of any model? Maybe you introduced new circular deps? Just looking at your few lines it's quite impossible to have any clues |
Here is the generated folder - and the schema - |
The error output looks like this - using Next js |
I'm running into the following error on all my models that are related to each other:
'TagTypeModelBase' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.
Here is the file in question:
UserModel.base.ts
Project
has a link back to theUser
model. When I first ran into this I found:https://github.com/mobxjs/mobx-state-tree#handle-circular-dependencies-between-files-and-types-using-late
and thought I could get around this by editing
UserModel.ts
like the following:But I still get the error in typescript. It seems like I need to edit
UserModel.base.ts
directly to fix this issue, but that is a generated file.The text was updated successfully, but these errors were encountered: