Version
2.4.0
Case
When defining model it isn't unusual to have a recursive structure, where one type circularly depends on another type.
Consider this:
Each Entity requires to have information about Place, where it belongs. But each Place is an Entity.
Thus, we have a circular dependency:
// entity.js
import Place from './place'
export const Entity = t.interface({
place: Place
})
// place.js
import Entity from './entity'
export const Place = Entity.extend({})
Seems like there is no way to express such a relationship with tcomb, and current tcomb tooling makes it impossible to workaround.
Thoughts
Issue isn't related to the tcomb itself and rather a technical limitation of current modules implementation, but I found myself struggling to work around that issue with tcomb tools.
The root of the issue is that all tcomb declarations are "eager". They evaluated as soon as module loaded, and because another module isn't resolved yet either place.js will complain that it can't extend undefined (Entity which isn't loaded yet), or entity.js will complain that its interface declaration is faulty (because Place ends up undefined).
So, it feels like there should be a way to make type evaluation "lazy" — to force it to evaluate when used (and by that time in most case all variables should resolve), and not when declared. However, it means that meta information won't be available statically on type...
t.declare('Type') and Type.define doesn't help here much too, since it will be in same way eagerly evaluated and end up with broken types. Or maybe I'm missing obvious way how it helps in such situations?
I think maybe it could help if define could accept a function rather than a type definition.
However, to be honest, I wasn't able to come up with a good solution yet. Maybe someone knows the solution.
Version
2.4.0Case
When defining model it isn't unusual to have a recursive structure, where one type circularly depends on another type.
Consider this:
Each
Entityrequires to have information aboutPlace, where it belongs. But eachPlaceis anEntity.Thus, we have a circular dependency:
Seems like there is no way to express such a relationship with
tcomb, and currenttcombtooling makes it impossible to workaround.Thoughts
Issue isn't related to the
tcombitself and rather a technical limitation of current modules implementation, but I found myself struggling to work around that issue withtcombtools.The root of the issue is that all
tcombdeclarations are "eager". They evaluated as soon as module loaded, and because another module isn't resolved yet eitherplace.jswill complain that it can't extend undefined (Entitywhich isn't loaded yet), orentity.jswill complain that its interface declaration is faulty (becausePlaceends up undefined).So, it feels like there should be a way to make type evaluation "lazy" — to force it to evaluate when used (and by that time in most case all variables should resolve), and not when declared. However, it means that meta information won't be available statically on type...
t.declare('Type')andType.definedoesn't help here much too, since it will be in same way eagerly evaluated and end up with broken types. Or maybe I'm missing obvious way how it helps in such situations?I think maybe it could help if
definecould accept a function rather than a type definition.However, to be honest, I wasn't able to come up with a good solution yet. Maybe someone knows the solution.