Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

setmetatable() doesn't apply metatable to type intersections #983

Open
funwolf7 opened this issue Jul 24, 2023 · 0 comments
Open

setmetatable() doesn't apply metatable to type intersections #983

funwolf7 opened this issue Jul 24, 2023 · 0 comments
Labels
bug Something isn't working

Comments

@funwolf7
Copy link

If you call setmetatable with an intersection of two or more tables, the resulting type will not have the metatable applied to it. This causes issues with typechecking, as attempting to access something in the __index will cause a type error. I have wrote the following sample code, which mimics a typical OOP setup you might see:

--!strict

local Index = {}
local Metatable = {
	__index = Index,
}

function Index.GetName(self: Foo): string
	return self.Name
end

type props1 = {
	Name: string,
}
type props2 = {
	Value: any,
}
type fooProps = props1 & props2 -- If props2 were removed from this line, there would be no issues

-- The type does not include the metatable
type Foo = typeof(setmetatable({} :: fooProps, Metatable)) -- type Foo = { Name: string } & { Value: any }

-- Trying to set an object with the same metatable to be the type Foo doesn't work
local testFoo: Foo = setmetatable({
	Name = "Test",
	Value = 1,
}, Metatable) -- TypeError: Type '{ @metatable Metatable, { Name: string, Value: number } }' could not be converted into 'props1 & props2'

-- Since the type Foo doesn't have an __index, functions in Index are not usable
testFoo:GetName() -- TypeError: Type 'props1 & props2' does not have key 'GetName'

This occurs in both strict and nonstrict mode.

I ran into this issue myself, as I have 2 objects with certain shared properties between them. To simplify the code and allow for easier modifications in the future, I want to store the shared properties in one type and make each object intersect it with a type containing the unique properties for that object before setting the metatable. Unfortunately, this bug makes that idea impossible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Development

No branches or pull requests

1 participant