I was recently brain-storming with a friend of mine trying to wrap our heads around why only some class functions were able to utilize “self” in an attempt to make writing a class easy and without explicit definition.
It’s 100% possible AS LONG AS the functions underneath the class were explicitly used (not in a loop of some kind, has to be typed out like self:Function() ) Video :
I expected the class to automatically pick up intelli-sense from within the functions just via metatables without having to explicitly run a function in its constructor method.
The reason this doesn’t work is because nothing about the code actually requires that the type of self in Explode be the same type as the type of the self variable in your constructor without the call to it. That’s why you see a plain free type a for self, it’s entirely unconstrained.
This is definitely the worst kind of “technically correct” since we understand that humans write colon definitions expecting the self types to all be consistent, but as-is this is more of a feature request for a change to type inference than a bug.
This restriction on type inference is nevertheless already a planned addition to the Luau language, described here as “shared self types”. It will be implemented as part of the New Type Solver after it is released generally (i.e. when it is out of beta).
The work around I found for this is to reflect self as a type from the constructor.
local BUILDING = {}
BUILDING.__index = BUILDING
-- Constructs a new building.
function BUILDING.new(BuildingObject : Model)
local self = setmetatable({}, BUILDING)
self.Parts_Destroyed = 0
return self
end
-- Causes the building to explode.
function BUILDING:Explode()
local self : typeof(BUILDING.new()) = self
self.Parts_Destroyed += 20
end
return BUILDING
local BUILDING = {}
BUILDING.__index = BUILDING
-- Constructs a new building.
function BUILDING.new(BuildingObject : Model)
return setmetatable({
Parts_Destroyed = 0
}, BUILDING)
end
export type Building = typeof(BUILDING.new())
-- Causes the building to explode.
function BUILDING.Explode(self: Building)
self.Parts_Destroyed += 20
end
return BUILDING
It’s pretty tedious writing local self: type = self and it’s redeclaring a variable when you don’t need to
Also this way you can use the type outside the methods