luau
luau copied to clipboard
Type error occurs when using templated methods during table iteration
Reproduction
For example, in this code:
type Class = {
method: <T>(Class, T) -> T
}
local objects: { Class } = {}
for _, object in objects do
object:method(123) -- ERROR
end
The following error is raised on the object:method(123) line:
TypeError: Type 'Class' from 'example.lua' could not be converted into 'Class' from 'example.lua'
caused by:
Property 'method' is not compatible.
Type
'(Class, number) -> number'
could not be converted into
'<T>(Class, T) -> T'; different number of generic type parameters
Impact
You don't even have to call the method in order to experience the issue. For example, your template method could be buried in a descendant class:
type Class = { method: <T>(Class, T) -> T }
type Parent = {
child: Class,
foo: (Parent) -> (),
}
local parents: { Parent } = {}
for _, parent in parents do
parent:foo() -- 'Parent' could not be converted into 'Parent'
end
This, and the nonsense message, makes the error very frustrating.
Workaround
for _, object in objects do
(object :: Class):method(123) -- no error
end
This makes the code look very silly, since object is already a Class. It is also somewhat challenging to come up with this workaround on your own, and it's likely that people are just casting object :: any and destroying type safety.
For some additional context, I've been complaining about this in the Roblox OSS Discord for a while.
Same problem for a library here (https://github.com/alicesaidhi/skilift) Having to type cast it even outside of the library to stop the type errors is quite annyoing.