-
I want to declare an enum where the values are opaque (i.e. left to the implementation). Users should go through the enum to get to the actual value. The best I could come up with is to define opaque types for each enum variant. Is there a proper way to define an enum like this? The following is a minimal example: ---@meta
local _private_water
local _private_fire
---@enum EventType
EventType = {
Water = _private_water,
Fire = _private_fire,
}
---@class WaterEvent
---@class FireEvent
--- Listen to some event
---@param ty EventType.Water
---@param cb fun(event: WaterEvent)
---@overload fun(ty: EventType.Fire, cb: fun(event: FireEvent))
function listen(ty, cb) end -- intented use
listen(EventType.Water, function(event) end)
listen(EventType.Fire, function(event) end)
-- unintended use
listen("Water", function(event) end)
listen("Fire", function(event) end)
listen("foo", function(event) end) |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments
-
I know a hacky way to do so: ---@meta
---@enum EventType
EventType = {
Water = {}, ---@type EventType.Water
Fire = {}, ---@type EventType.Fire
}
---@class WaterEvent
---@class FireEvent
--- Listen to some event
---@param ty EventType
---@param cb function
---@overload fun(ty: EventType.Water, cb: fun(event: WaterEvent))
---@overload fun(ty: EventType.Fire, cb: fun(event: FireEvent))
function listen(ty, cb) end -- cb params can type narrow correctly
listen(EventType.Water, function(event) end)
listen(EventType.Fire, function(event) end)
-- all of below will throw `param-type-mismatch`
listen("Water", function(event) end)
listen("Fire", function(event) end)
listen("Wind", function(event) end) Credits: the gist link inside additional notes of this issue comment: #2758 (comment) AFAIK when declaring an |
Beta Was this translation helpful? Give feedback.
-
Thank you, that's good enough for my use-case! |
Beta Was this translation helpful? Give feedback.
I know a hacky way to do so: