The Crystal Programming Language Forum

Hash with Block/Proc

How to define ??? type on below code:

class Events
  alias EventHandlers = Hash(String, Array(???))

  @handlers : EventHandlers

  def initialize
    @handlers = EventHandlers.new
  end

  def add_handler(name, &block)
    unless @handlers[name]?
      @handlers[name] = Array(???).new
    end

    @handlers[name] << block
  end

  def fire_event(name, payload)
    if handlers = @handlers[name]?
      handlers.map(&.call(payload))
    end
  end
end

Using previous code

events = Events.new

events.add_handler("custom_event") do |payload|
  puts payload.inspect
end

event.fire_event("custom_event", payload: { foo: :bar })

If it’s Proc, I must specify types like Proc(*T, R), but I don’t want to care about Proc what’s returning, sometimes String, Int32, Nil or anythingelse.

It would most likely have to be a proc, could always just set the return type as Nil, pretty sure that would cause the proc to return nil even if its not the return value.

The bigger challenge will be the variable payload.

Coming from Ruby that feels natural, however in my experience it’s better not to sidestep the static analysis. If you really need an arbitrary payload, you may do what JSON::Any does using recursive aliases, which still restricts the types by the way, or you may forego this aspect of your program and for example start building types of Event, then just use the parent as the type restriction. Or a module, that should also work.

1 Like