Avoiding recursion when modules use types exported from eachother

Hi there!
I’ve run into a bit of an issue in the development of a couple of modules I am working on.
I am currently working with implementing some classes with an OOP-ish system using metatables, and I’d like for my code to be fully typechecked.
Two of my classes both contain fields who’s type is of the other class. Something like this:

-- Class 1
local Class1 = {}
Class1.__index = Class1

type self = {
    Field: Class2
}
export type Class1 = typeof(setmetatable({} :: self, Class1))

function Class1.new()
    local self = setmetatable({},Class1)
    return self
end)

function Class1:CreateClass2()
    self.Field = Class2.new(self)
end

return Class1
-- Class 2
local Class2 = {}
Class2.__index = Class2

type self = {
    Field: Class1
}
export type Class2 = typeof(setmetatable({} :: self, Class2))

function Class2.new(Field: Class1)
    local self = setmetatable({},Class2)
    self.Field = Field
    return self
end)

return Class2

This obviously does not work, as neither of these modules require eachother, and therefore doesn’t get the exported types. However if I try to require the other module in both classes, it will cause infinite recursion. Is there any way to get around this?

Any help is appreciated!

2 Likes

When you write two modules with cyclic dependencies, it is not quite recommended exactly. Can you refactor it in a way to avoid this two-way dependency?

Here are some relevant topics that are similar.

The only part of Class1 that Class2 is dependent on is the type for type annotation. The modules themselves are not dependant of eachother.

1 Like

I have the exact same problem and I feel like there is no solution. Roblox should fix this issue

1 Like

I had the same problem and the only solution I’ve found is to define types that use each other in the same ModuleScript.