I’m trying to write a module for a generic queue data structure with full type definitions but I can’t figure out how to structure the type descriptions.
Okay I found a solution and I’ll post it here for the next person who has a similar issue.
I’ll post the full class definition since there’s not that much and it illustrates this typing style better:
type self<T> = {
Contents: { T },
First: number,
Last: number,
}
local Queue = {}
Queue.__index = Queue
export type Queue<T> = typeof(setmetatable({} :: self<T>, Queue))
function Queue.new<T>(): Queue<T>
local self = setmetatable({} :: self<T>, Queue)
self.Contents = {}
self.First = 1
self.Last = 0
return self
end
function Queue.enqueue<T>(self: Queue<T>, item: T): ()
self.Last += 1
self.Contents[self.Last] = item
end
function Queue.dequeue<T>(self: Queue<T>): T
if self.First > self.Last then
error("Attempted to remove from an empty queue")
end
local item = self.Contents[self.First]
self.Contents[self.First] = nil
self.First += 1
return item
end
function Queue.len<T>(self: Queue<T>): number
return self.Last - self.First + 1
end
return Queue
Basically, instead of creating the type definition ahead of time, this style is dynamically generating it from the type definitions of the functions.
This style does require writing member functions a bit awkwardly (explicitly defining the type of self in each function definition) but overall I rather prefer it to the “header definitions” style from before.