// Defines a type that gets implemented later. This is useful when you have to deal with circular dependencies.
// Please notice that when defining circular dependencies TypeScript isn't smart enough to inference them.
// You need to declare an interface to explicit the return type of the late parameter function.
interface INode {
childs: INode[]
// TypeScript is'nt smart enough to infer self referencing types.
const Node = types.model({
childs: types.optional(types.array(types.late<any, INode>(() => Node)), [])
However, when implementing this example using TypeScript 2.5.2 (with noImplicitAny set to true), this results in the following TypeScript error:
TS7022:'Node' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.
If we set noImplicitAny in our TsConfig to false, then the error is gone. However, there is no typing information available on the MST model anymore. I can instantiate Node with any snapshot, without it ever triggering a typing error. I assume the snapshot resolves to the 'any' type, thus no type checking is performed in this case.
Are there any suggestions to solve this issue?
miguelrs, dsabanin, bhagyas, val-samonte, yang, dzcpy, liuliangsir, and clbg reacted with thumbs up emoji
platon-rov and liuliangsir reacted with thumbs down emoji
All reactions
It's not great but we've worked around this by explicitly typing the model reference:
import {types, IModelType} from 'mobx-state-tree';
interface INode {
childs: INode[]
const Node: IModelType<Partial<INode>, INode> = types.model({
childs: types.optional(types.array(types.late(() => Node)), [])
const node = Node.create();
node.childs; // INode.childs: INode[]
I have the same problem. Can someone give me a hand?
I look at the late
test and can find this:
test("late should allow circular references", () => {
// TypeScript is'nt smart enough to infer self referencing types.
const Node = types.model({
childs: types.optional(types.array(types.late(() => Node)), [])
expect(() => Node.create()).not.toThrow()
expect(() => Node.create({ childs: [{}, { childs: [] }] })).not.toThrow()
test("late should describe correctly circular references", () => {
// TypeScript is'nt smart enough to infer self referencing types.
const Node = types.model("Node", {
childs: types.array(types.late(() => Node))
expect(Node.describe()).toEqual("{ childs: Node[] }")
TypeScript is'nt smart enough to infer self referencing types.
Any idea what I should do if I'm using TypeScript? 😅
My case is a little trickier because I have other fields. For example,
const Node = types.model("Node",{
name: types.string,
age: types.number,
children: types.array( types.late(() => Node )
How can I modify the workaround about to handle this case?
Thank you 🙌
Edit: Yay! I got it! 😃🎉
In case any other noobs (like me) stumble onto this, maybe this will help:
interface INode {
name: string;
age: number;
children: INode[];
const Node: IModelType<Partial<INode>, INode> = types.model("Node", {
name: types.string,
age: types.number,
children: types.optional(types.array(types.late(() => Node)), [])
});
So am I correct that the only way to solve 'circular dependency' issues with TypeScript is to create all needed TS interfaces manually (?) and use it because MST makes everything as any
(after types.late
usage)? It sounds like very complex solution for big models with many fields, lists, etc...Is there any other way?
I'm currently doing some conferences, on which I really have to focus, so I
hope it can wait two weeks 😊
Op do 25 okt. 2018 18:39 schreef Rainer Wittmann <
[email protected]>: