How would I type annotate an inherited Object?

I’m trying out annotations for the first time & doing my best to integrate it with magnalite’s method of abstraction & object creation. Although the base class is functional, I can’t figure out how I would annotate an inherited class, if that’s even at all possible.

Base Object Class:

--!strict

-- Module Table
local Object = {}
Object.__index = Object

-- Object Type
type ObjectType = typeof(setmetatable({}, Object))





--[[ Constructor: Returns an instance of the ObjectType class. ]]
function Object.new(arg1: number, arg2: boolean): ObjectType
	local self = setmetatable({}, Object)
	
	-- Properties
	self.Number = arg1
	self.Bool = arg2

	return self
end



--[[ Get Number: Returns the object's number. ]]
function Object:getNumber(): number self = self::ObjectType
	return self.Number :: number
end



--[[ Get Number: Returns the object's bool. ]]
function Object:getBool(): boolean self = self::ObjectType
	return self.Bool :: boolean
end



-- Module Table
return Object

Inherited Object Class:

--!strict

-- Parent Class
local BaseObject = require(script.Parent)

-- Module Table
local inheritedObject = setmetatable({}, BaseObject)
inheritedObject.__index = inheritedObject

-- Object Type
type inheritedObjectType = typeof(setmetatable({}, BaseObject)) & typeof(setmetatable({}, inheritedObject))

-- Colour Type
type colour = "blue"| "red" | "green"





--[[ Constructor: Returns an instance of the inheritedObjectType class ]]
function inheritedObject.new(arg1: number, arg2: boolean, arg3: colour): inheritedObjectType
	local self = setmetatable({BaseObject.new(arg1,arg2)}, inheritedObject) :: inheritedObjectType
	
	-- Properties
	self.Colour = arg3
	
	return self
end



--[[ Get Colour: Returns the object's colour. ]]
function inheritedObject:getColour(): colour self = self::inheritedObjectType
	return self.Colour :: colour
end



-- Module Table
return inheritedObject

Currently the InheritedObject class will only autofill for the base class’s functions & properties while not allowing me to add any new ones either. It doesn’t override the base functions either. I would appreciate any kind of explanations or possible errors I could’ve made.

I believe for any sort of inheritance, you would have to type out all the members of the inherited class, ie:

type inheritedObjectProps = {
	Colour: colour;
}

type inheritedObjectMethods = {
	getColour: (self: inheritedObjectType) -> colour;
	
	__index: inheritedObjectMethods;
}

type inheritedObjectType = typeof(setmetatable({} :: inheritedObjectProps, {} :: inheritedObjectMethods)) & ObjectType

--[[ Constructor: Returns an instance of the inheritedObjectType class ]]
function inheritedObject.new(arg1: number, arg2: boolean, arg3: colour): inheritedObjectType
	local self = setmetatable(Object.new(arg1,arg2) :: any, inheritedObject)

	-- Properties
	self.Colour = arg3

	return self :: inheritedObjectType
end

local a: inheritedObjectType
-- a should now autocomplete for all members
1 Like

First Issue: Inheritance still doesn’t seem to work, the inherited object does not contain any of the parent methods or properties. I believe this is due to setmetatable() being a table function, & by creating our own return type it prevents us from utilizing it since the type checker no longer recognizes it as such. I think a viable way to circumvent this might be to store & unload the parent’s properties/methods directly into the inherited object? Although that sounds like it would be messy in comparison.

Second Issue: Autocomplete doesn’t function internally (within any of the methods) except the main constructor.

Typing out all of the members to each class seems to have fixed some of the other issues I had though.

That’s odd, I’m not getting any of these issues, do you have the new type solver enabled by chance?



This is my current setup:

Summary
-- Module Table
local Object = {}
Object.__index = Object

-- Object Type
type ObjectType = typeof(setmetatable({}, Object))


--[[ Constructor: Returns an instance of the ObjectType class. ]]
function Object.new(arg1: number, arg2: boolean): ObjectType
	local self = setmetatable({}, Object)

	-- Properties
	self.Number = arg1
	self.Bool = arg2

	return self
end

--[[ Get Number: Returns the object's number. ]]
function Object:getNumber(): number self = self::ObjectType
	return self.Number :: number
end

--[[ Get Number: Returns the object's bool. ]]
function Object:getBool(): boolean self = self::ObjectType
	return self.Bool :: boolean
end

-----------------------------------------------------------

local BaseObject = Object

type inheritedObjectProps = {
	Colour: colour;
}

type inheritedObjectMethods = {
	getColour: (self: inheritedObjectType) -> colour;

	__index: inheritedObjectMethods;
}

type inheritedObjectType = typeof(setmetatable({} :: inheritedObjectProps, {} :: inheritedObjectMethods)) & ObjectType

type colour = "blue"| "red" | "green"

local inheritedObject = setmetatable({}, BaseObject)
inheritedObject.__index = inheritedObject

--[[ Constructor: Returns an instance of the inheritedObjectType class ]]
function inheritedObject.new(arg1: number, arg2: boolean, arg3: colour): inheritedObjectType
	local self = setmetatable(Object.new(arg1,arg2) :: any, inheritedObject)

	-- Properties
	self.Colour = arg3

	return self :: inheritedObjectType
end

function inheritedObject:getColour(): colour self = self::inheritedObjectType
	return self.Colour :: colour
end

local a = inheritedObject.new(1, true, 'red')

a:getNumber()

Edit: also if you are using an external module for the parent type, in the base class you need to export the type

export type ObjectType = typeof(setmetatable({}, Object))

and then in the inherited object, you’d need to reference it by the module variable name

local BaseObject = require(script.ModuleScript)

-- ...

type inheritedObjectType = typeof(setmetatable({} :: inheritedObjectProps, {} :: inheritedObjectMethods)) & BaseObject.ObjectType
1 Like

I solved the issue, I just chose not to reply as to not unnecessarily bump the topic.

I was confused because I was not receiving any autocomplete features within the object, but all I needed to do was reinsinuate the type.
I edited,
local self = setmetatable(Object.new(arg1,arg2) :: any, inheritedObject)
into,
local self = setmetatable(Object.new(arg1,arg2) :: any, inheritedObject) :: inheritedObject
Which enabled all of the object’s properties & methods once again.

As for the second issue I must’ve have made a minute error somewhere, but I found this small section of the lua type checking article with code that functioned, while mine did not… so I scrapped my original script & pulled in the example from the article which I reconfigured to my liking.

Thank you for your replies, I appreicate your help!

1 Like

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