luau
luau copied to clipboard
Parameter types with methods are different depending on `.` or `:` calling
local Class = {}
Class.__index = Class
function Class.new<T>(Data: T)
return setmetatable({ Data = Data }, Class)
end
type Class<T> = typeof(Class.new((nil :: any) :: T))
function Class.Update<T>(self: Class<T>, Update: (T) -> T)
self.Data = Update(self.Data)
end
function Class.Get<T>(self: Class<T>): T
return self.Data
end
local inst = Class.new({
Text = "Hello, World",
})
inst:Update(function(Data)
-- Type of Data is `a` here - incorrect behavior
return Data
end)
inst.Update(inst, function(Data)
-- Type of Data is `{ Text: string }` here - correct behavior
return Data
end)
local value = inst:Get()
-- Type of value is `{ Text: string }` here
Depending on if Update
is called using a .
or :
the types of the parameters change - specifically when using generics. The Get
example shows how this doesn't apply to returns, just parameters.
I don't believe the types changing between using :
or .
with the same self object is intentional.
typing skill issue
--!strict
local class = {}
class.__index = class
type class<T> = {
__index: class<T>,
new: (Data: T) -> Widget<T>,
Update: (self: Widget<T>, Update: (T) -> T) -> (),
}
export type Widget<T> = typeof(setmetatable({} :: {}, class :: class<T>))
function class.new<T>(Data: T): Widget<T>
return setmetatable({
Data = Data
}, class :: class<T>)
end
function class:Update<T>(Update: (T) -> T)
self.Data = Update(self.Data)
end
local object = class.new(
{
Text = "Hello, World!"
}
)
object:Update(function(Data)
return Data -- Data is not 'a' here but {Text: string} - correct behaviour
end)
fixed by new solver