Why is gets typed as 'any' when you have a return

inside meta.isMeta, when i try to do self.meta2:isMeta() it doesn’t autocomplete because meta2 is typed as ‘any’ but when i remove the return at the beginning, it gets typed


local meta2 = {}
meta2.__index = meta2

type meta2 = setmetatable<{
	isMeta: boolean,
}, {
	__index: typeof(meta2)
}>

function meta2.new(): meta2
	return setmetatable({
		isMeta = true,
	}, meta2) :: any
end

function meta2.returnIsMeta(self: meta2)
	return self.isMeta
end

local meta = {}
meta.__index = meta

type meta = setmetatable<{
	isMeta: boolean,
	meta2: meta2
}, {
	__index: typeof(meta)
}>

function meta.new(): meta
	return setmetatable({
		isMeta = true,
		meta2 = meta2.new()
	}, meta) :: any
end

function meta.returnIsMeta(self: meta)
	if self.isMeta == false then
		return
	end
	
	self.meta2:returnIsMeta()
end

its because it returns a value

Looks like Luau type inference is getting confused here. The combination of the bare early return and the :: any casts in the constructors often causes fields (like meta2) to fallback to any

Try:

  1. Remove the :: any casts from both new functions
  2. Change the early return to return nil (or type the method as boolean?)
function meta.returnIsMeta(self: meta): boolean?
	if self.isMeta == false then
		return nil
	end
	return self.meta2:returnIsMeta()
end

That usually restores the autocomplete for self.meta2