Typechecking with OOP Metatables

I am trying to make a strict-typechecking compatible custom tween wrapper (OOP) class. I’ve seen this post regarding the same topic, but that solution did not work for me. My current code:

-- Setup --
local Tween = {}
Tween.__index = Tween

-- Lua Types --
type TweenInfoTable = {
	Time: number?,
	EasingStyle: Enum.EasingStyle?,
	EasingDirection: Enum.EasingDirection?,
	RepeatCount: number?,
	Reverses: boolean?,
	DelayTime: number?
}

type CustomTween = typeof(setmetatable({}, Tween)) & {
	Tween: Tween?,

	Object: Model | Instance,
	TweenInfo: TweenInfo,
	Data: { [string]: any },
	
	Play: () -> nil,
	Pause: () -> nil,
	Cancel: (Destroy: boolean) -> nil,
	Destroy: () -> nil,
}

-- Functions --
local TableToTweenInfo = function(Info: TweenInfoTable) : TweenInfo ... end

-- Constructor --
function Tween.new(Object: Model | Instance, Info: TweenInfoTable, Data: { [string]: any} ) : CustomTween
	local Info = TableToTweenInfo(Info)
	
	local _Tween = {
		Tween = nil,
		
		Object = Object,
		TweenInfo = Info,
		Data = Data,
	}
	
	setmetatable(_Tween, Tween)
	
	return _Tween
end

The error the linter is giving me is:

Type Error: (67,2) Type '{ @metatable Tween, { Data: {| [string]: any |}, Object: Instance | Model, ... 2 more ... } }' could not be converted into '{ @metatable Tween, { Data: {| [string]: any |}?, Object: (Instance | Model)?, ... 2 more ... } } & {| Cancel: (boolean) -> nil, Data: {| [string]: any |}, ... 6 more ... |}'
caused by:
  Not all intersection parts are compatible. Type '{ @metatable Tween, { Data: {| [string]: any |}, Object: Instance | Model, ... 2 more ... } }' could not be converted into '{| Cancel: (boolean) -> nil, Data: {| [string]: any |}, ... 6 more ... |}'

return setmetatable(_Tween :: any, Tween) :: CustomTween
not sure if this is the best way of going about it, but its how i do it and it seems to work

3 Likes