You can sort of do this with typecasting. Here’s how I set up my own classes, basically:
-- Class is its own type
export type Class =
{
-- Methods
Method: (self: Class) -> ();
-- Members
someValue: number;
}
-- Separate static functions from class methods
type Static =
{
new: () -> Class;
}
-- Implementation is completely separate
type ClassImpl =
{
__index: ClassImpl;
} & Static & Class -- Union the static functions and the class methods
local Class: ClassImpl = {} :: ClassImpl
Class.__index = Class
function Class.new(): Class
local self: Class = {
someValue = 2;
} :: Class
setmetatable(self :: any, Class)
return self
end
-- VERY IMPORTANT!
-- The typecast makes it so only the static functions are exposed to other scripts
return Class :: Static
So, only your methods and members are exposed for anything that is of type Class. But, your static functions like the constructor are limited to whatever requires the module.