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

Typing getRoot doesn't work with TypeScript 3.5 #1330

Closed
3 tasks done
mekwall opened this issue Jul 4, 2019 · 8 comments
Closed
3 tasks done

Typing getRoot doesn't work with TypeScript 3.5 #1330

mekwall opened this issue Jul 4, 2019 · 8 comments

Comments

@mekwall
Copy link

mekwall commented Jul 4, 2019

Bug report

  • I've checked documentation and searched for existing issues
  • I've made sure my project is based on the latest MST version
  • Fork this code sandbox or another minimal reproduction.

Sandbox link or minimal reproduction code

The following minimal repro works as expected with TS 3.4 but not 3.5.

import { types, getRoot } from "mobx-state-tree";

const ChildStore = types
  .model("ChildStore", {
    foo: types.string,
    bar: types.boolean
  })
  .views(self => ({
    get root() {
      return getRoot<typeof RootStore>(self);
    }
  }))
  .actions(self => ({
    test() {
      const { childStore } = self.root;
      // childStore and childStore.foo is properly inferred in TS 3.4 but not in 3.5
      console.log(childStore.foo);
    }
  }));

const RootStore = types.model("RootStore", {
  childStore: ChildStore
});

Describe the expected behavior
Typing getRoot should work with TS 3.5 as it does in 3.4.

Describe the observed behavior
As soon as RootStore is referenced by type to getRoot it breaks type inference and RootStore becomes any.

@mweststrate
Copy link
Member

Should afaik be `return getRoot<Instance>(self);

@mekwall
Copy link
Author

mekwall commented Jul 15, 2019

@mweststrate But it works just fine in TS 3.4 and it's the same as in #951 (comment).

@mweststrate
Copy link
Member

Not sure why it changed in 3.5 (or why it succeeded in 3.4), but can confirm that breaking the circular type with an interface fixes the problem:

const ChildStore = types
        .model("ChildStore", {
            foo: types.string,
            bar: types.boolean
        })
        .views(self => ({
            get root(): IRootStore {
                return getRoot<IRootStore>(self)
            }
        }))
        .actions(self => ({
            test() {
                const { childStore } = self.root
                // childStore and childStore.foo is properly inferred in TS 3.4 but not in 3.5
                console.log(childStore.foo)
            }
        }))

        interface IRootStore extends Instance<typeof RootStore> {}

    const RootStore = types.model("RootStore", {
        childStore: ChildStore
    })

mweststrate added a commit that referenced this issue Jul 19, 2019
@mweststrate
Copy link
Member

Should work with the above setup in 3.14.1

@kuceb
Copy link

kuceb commented Sep 2, 2019

I was using the views get root() approach, however with multiple ChildStore models, typescript will start to get flaky when resolving circular references. Everything would be fine, then I would reload VSCode and my RootStore would be any typed again, giving me an error.

I got it to work consistently by writing out interfaces for each of my ChildStore models as well, then creating an IRootStore interface like so:

interface IChildOne extends Instance<typeof ChildOne>{}
const ChildOne = types.model({})
  .views(self => ({
    get root(): IRootStore {
      return getRoot(self)
    },
  }))
  .actions(self => ({
    fooAction() {
      const childThreeProp = self.root.childThree.someprop
    // childThreeProp is properly typed, RootStore not `any`
    },
  }))

// other children defined similarly here

export interface IRootStore {
  childOne: IChildOne
  childTwo: IChildTwo
  childThree: IChildThree
}
export const RootStore = types.model({
  childOne: ChildOne,
  childTwo: ChildTwo,
  childThree: ChildThree,
})

This method adds some boilerplate, but seems to be the most consistent solution for me until Typescript fixes the circular reference types issues. Thank you for not making this project rely on code generation 😄

@ecklf
Copy link

ecklf commented Jan 2, 2020

@bkucera thank you, I managed to finally get it working with your solution! Breaking the circular type with an interface as @mweststrate suggested however did not do the trick for me (same error). Seems we are stuck with this workaround (TypeScript 3.7.4).

@kuceb
Copy link

kuceb commented Jan 2, 2020

For anyone still having problem with typescript flakiness, I recommend classy-mst. Moving to typescript classes fixed all my typings issues.

@lock
Copy link

lock bot commented Mar 10, 2020

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs or questions.

@lock lock bot locked as resolved and limited conversation to collaborators Mar 10, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants