Metatable type defect with merged table types (&)

Non-validating code:

--!strict

export type abstract_raw_schema = {
	_foo: number,
}

export type abstract_index_schema = {
	Bar: (abstract_schema ) -> (),
}
export type abstract_schema = typeof(setmetatable({}::abstract_raw_schema, {__index={}::abstract_index_schema}))

export type normal_raw_schema = abstract_raw_schema & {
	_baz: number,
}
export type normal_index_schema_tmp = {
	Qux: (normal_schema ) -> (),
}
export type normal_index_schema = typeof(setmetatable({}::normal_index_schema_tmp, {__index={}::abstract_index_schema}))
export type normal_schema = typeof(setmetatable({}::normal_raw_schema, {__index=({}::any)::normal_index_schema}))

local t: normal_schema = nil -- just for testing
-- PROBLEM: t:Bar() & t:Qux() shows as non-existant!
-- culprit is that normal_raw_schema consists of abstract_raw_schema & something else. works fine if I just use 'abstract_raw_schema'

Validating code but with another defect:

--!strict

export type abstract_raw_schema = {
	_foo: number,
}

export type abstract_index_schema = {
	Bar: (abstract_schema) -> (),
}
export type abstract_schema = typeof(setmetatable({}::abstract_raw_schema, {__index={}::abstract_index_schema}))

export type normal_raw_schema = abstract_raw_schema --[[& {
	_baz: number,
}]]
export type normal_index_schema_tmp = {
	Qux: (normal_schema) -> (),
}
export type normal_index_schema = typeof(setmetatable({}::normal_index_schema_tmp, {__index={}::abstract_index_schema}))
export type normal_schema = typeof(setmetatable({}::normal_raw_schema, {__index=({}::any)::normal_index_schema}))

local t: normal_schema = nil -- just for testing
t:Qux() -- validates and works fine now!
t:Bar() -- does not show up in intellisense also does not validate!

Working example:

--!strict

local module = {}


--- Abstract types/implementation
export type abstract_raw_schema = {
	_foo: number,
}

export type abstract_index_schema = {
	Bar: (self: abstract_schema) -> (),
}
export type abstract_schema = typeof(setmetatable({}::abstract_raw_schema, {__index={}::abstract_index_schema}))

local abstract_prototype = {}
function abstract_prototype.Bar(self: abstract_schema)
	print("Bar")
end


--- Normal types/implementation
export type normal_raw_schema = abstract_raw_schema & {
	_baz: number,
}
export type normal_index_schema_tmp = {
	Qux: (self: normal_schema) -> (),
}
export type normal_index_schema = typeof(setmetatable({}::normal_index_schema_tmp, {__index={}::abstract_index_schema}))
export type normal_schema = typeof(setmetatable({}::normal_raw_schema, {__index=({}::any)::normal_index_schema}))

local normal_prototype = {}
setmetatable(normal_prototype, {__index=abstract_prototype})
function normal_prototype.Qux(self: normal_schema)
	print("Qux")
end


--- Test
local self: normal_raw_schema = {
	-- Abstract
	_foo = 1,
	-- Normal
	_baz = 2,
}
local self: normal_schema = setmetatable(self, {__index=normal_prototype})
self:Qux()  -- does not validate, but works
self:Bar() --  does not validate, but works

return module
1 Like

Thanks for the report.We’ll follow up when we have an update for you.

1 Like