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

Bidirectional references and typing #658

Closed
cstranex opened this issue Feb 14, 2018 · 9 comments
Closed

Bidirectional references and typing #658

cstranex opened this issue Feb 14, 2018 · 9 comments

Comments

@cstranex
Copy link

I have two models that reference each other:

// ./modelA.ts
import {types, IModelType} from 'mobx-state-tree';
import { IMod, Mod } from './modelA';

const NormalNode = types.model({
    test: types.string
})

type NormalNodeType = typeof NormalNode.Type;

export interface INode extends NormalNodeType {
   child?: IMod | null
}

export const Node: IModelType<Partial<INode>, INode> = types.compose(types.model({
   child: types.maybe(types.reference(types.late(() => Mod))),
   example: types.string
}), NormalNode);
// ./modelB.ts
import {types, IModelType} from 'mobx-state-tree';
import { INode, Node } from './modelA';

const NormalMod = types.model({
    name: types.string
})
type NormalModType = typeof NormalMod.Type;

export interface IMod extends NormalModType {
    node?: INode | null;
}

export const Mod: IModelType<Partial<IMod>, IMod> = types.compose(types.model({
    node: types.maybe(types.reference(types.late(() => Node))),
}), NormalMod).actions(
    self => ({
        createSomeName: () => {
            self.name = 'test';
        }
    })
);
// ./index.ts
import { Node } from './modelA';

const store = Node.create();
store.test // available
store.child // available
store.example // not found

I have followed the example of #417 and explicitly defined interfaces for the references however in that example you have to explicitly type your entire model (ie: the example property is not available in Node). Is there another alternative besides defining a model with references and one without and composing them together as in above?

@mweststrate
Copy link
Member

I tried, but TypeScript really doesn't seem to be able to make sense of stuff anymore as soon as the type definitoins become bidirectional :-(.

@aksonov
Copy link

aksonov commented Oct 25, 2018

Maybe we should ask Typescript authors to improve that? If types.late breaks 'automatic' typing of whole model then we have to use/create some other way...

@aksonov
Copy link

aksonov commented Oct 25, 2018

UPDT: Just found nice workaround here - set any as return type for types.late (maybe you could do it as default option) - this way all typings will be preserved except 'recursive' fields

@xaviergonz
Copy link
Contributor

@aksonov
Copy link

aksonov commented Oct 25, 2018 via email

@xaviergonz
Copy link
Contributor

will change the docs to any then, thanks!

@xaviergonz
Copy link
Contributor

Btw, the same trick can be done for bidirectional refs (only needs to be done in one of the sides though)

@aksonov
Copy link

aksonov commented Oct 26, 2018

@xaviergonz My fault, IAnyModelType also works, I just tried to use types.late around types.reference (and that is incorrect). Now I use types.reference(types.late(..)) and `IAnyModelType works well

@xaviergonz
Copy link
Contributor

changed back :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants