Type sharing across modules: what is the best practice for typechecking?

Hey!
Having problems with Type contracts.

So, let’s say I have two modules:
TypesA; TypesB
And they are for:
ModuleA; ModuleB respectively.

ModuleA uses TypesA for all its types, and vice versa.
TypesB requires TypesA to access some of the types it stores. It needs it to be implemented in a Type for ModuleB.

How would I make it so that TypesA can acquire a type from TypeB without recursively requiring?

Is there better practice to do this kind of stuff?

In my current dillemma, I have a module: PlayerController.
This module manages every clientside module for the player.
I want it to be able to type check a ClientModule inside of itself, so like

self.Modules = {
  Module1 = RequiredModule1 : Types.RequiredModule1Class
}

And then any modules underneath PlayerController can access self.Modules and they can communicate.

However, in my current configuration, this doesn’t work, as it results in a cyclic dependency like mentioned before.

Is the only solution to simply have one Types module that’s massive?

I just have ModuleScripts that return a single value (i.e. true/false), but act completely like C-style header files for other modules.

1 Like

You can put the types in a separate module, typically named “Types”, this does make it a bit more tedious to update and maintain but it solves the dependancy issue.

1 Like

So would this mean just a big ol’ types module with all the types of classes in my game?

Could you please elaborate on what you mean by this? I’m not familiar with C

Basically just have a module like this:

export type fr = {}

return nil

To store types.

You can do that if you’d like, personally I only have it for a specific system if it’s needed to resolve a dependancy issue rather than game-wide.

Header files store type, class, member and function definitions. They can contain declarations of what files to include too (though you can do this in the .c file and forward-declare classes from the header).

I use it for types that are shared across the server and client mainly. If multiple scripts on the server or client need the same set of types defined, then I have them as a module just to make it tidy.

A big module full of types is useful if your types reference each other. But I’d advise you just have a type definition module per system for scripts to interact with it properly.

I do this. It’s just, I have separated the ‘type’ modules into different modules for structuring, but seems like this doesn’t work. LuaU doesn’t have something like TypeScript where you can just import types, correct? (though I’m not familiar with TypeScript myself)

This is what I do, yes.

My problem is two of these ‘header files’ need to require each other for their types, which results in a cyclic dependency.

Seems like I just have to make one big header file.

Or maybe split them up into base types and complex types?
Base types being types that are defined only with Luau native and ROBLOX object types, while Complex Types being made up of those and userdata/self-defined types.

If that doesn’t work, you can always keep the base-types separate, and the complex types defined in each script that requires them (though it’ll be a major hassle to deal with).

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.