Need help with understanding type definitions and how to use them #575
-
I am trying to figure out how type definitions work. At the moment, I see two different kinds of type definitions: ClassThese are "fake" types, in that they don't represent anything in real lua native values. These are only useful for typechecking/autocompletion etc.. Two major use cases. adding types for UserDatadeclare class Color
end
declare class Canvas
function draw_circle(self, radius: number, color: Color): nil
end Here, luau has no idea what the actual backing type of adding types for Vector (or other builtins)declare class Vector2
x: number
y: number
end
declare class Vector3 extends Vector2
z: number
end
declare function vector(x: number, y: number, z: number): Vector3 This is useful, so that I can typecheck vectors or cast type = { }This is a real native type. type Vector4 = {
x: number,
y: number,
z: number,
w: number
} This is useful when you know the structure of the table, and make sure that you are creating the right type. With this knowledge, I set out to write types for my application (skia bindings for luau). I wanted to have a declare class Rect
min: Vector2
max: Vector2
function area(self) : number
end But, I can't create a rect in lua now. The following code errors, because the types don't match. It wants a class, but I am providing it with a local rect: Rect = {
min = Vector2.default,
max = Vector2.default,
} Well, whatever, I will just use export type Rect = {
min: Vector2,
max: Vector2
} Its fine, but I don't want to store Here comes the problem. How do I declare the type now? -- this is fine
local rect: Rect = {
min: Vector2.default,
max: Vector2.default,
}
local rect_meta = {
function area(rect: Rect)
-- impl
end
}
-- but this is not. we will get the error that the return type of setmetatable is not Rect
local rect: Rect = setmetatable(rect, rect_meta) I was hoping that someone more familiar with luau's type system can help me figure it out. How do I create a Rect with metatable and proper typechecking? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
found the answer in roblox docs https://create.roblox.com/docs/luau/type-checking#defining-an-inferred-type you can get the type of an expression by using -- type of the rectangle's metatable that will be shared by all rect instances
type RectMeta = {
__index: RectMeta,
area: (self: Rect) -> number,
}
-- type of rect's "instance" (data unique to each instance)
type RectInstance = {
min: Vector2,
max: Vector2
}
-- now, we use typeof to get the inferred type of the expression
-- the expression is simply calling the `setmetatable` function with two empty tables.
-- cast the table to the "instance" data type of rect (the points)
-- cast metatable to the type of RectMeta
export type Rect = typeof( setmetatable( {} :: RectInstance, {} :: RectMeta) ) OTOH, we can actually use declare class Rect
min: Vector2
max: Vector2
function area(self) : number
end Then, this code will error local rect: Rect = {
min = Vector2.default,
max = Vector2.default,
} This is because we are assigning a table into a class, which is not allowed. Can we type cast it using The solution is to escape the typesystem temporarily and typecast the expression into local rect: Rect = {
min = Vector2.default,
max = Vector2.default,
} :: any Of course, only use |
Beta Was this translation helpful? Give feedback.
found the answer in roblox docs https://create.roblox.com/docs/luau/type-checking#defining-an-inferred-type
you can get the type of an expression by using
typeof
and use that to define a type. For the rect code above, we need to simply