Reputation: 550
I'm trying to implement a class which accepts a generic payload and then converts it to JSON:
require "json"
class Response
alias Payload = Hash(Symbol | String, String | Bool | Int32 | Int64 | Float32 | Float64 | Nil)
@payload : Payload
def initialize(@payload, @method : String = "sendMessage")
end
def to_json
@payload.merge({"method" => @method}).to_json
end
end
Response.new({
"chat_id" => update.message.not_nil!.chat.id,
"text" => "Crystal is awesome but complicated",
})
But I get instance variable '@payload' of Response must be Hash(String | Symbol, Bool | Float32 | Float64 | Int32 | Int64 | String | Nil), not Hash(String, Int64 | String)
compiler error. How can I overcome this? Does Crystal support generic Hashes? Why it can't convert even if types overlap?
The Response
is a part of a shard, so I don't know which hashes would be passed as arguments, but Payload
has to be enough.
Upvotes: 1
Views: 662
Reputation: 5661
Your payload hash is of type Hash(String, Int32 | String)
:
typeof({
"chat_id" => update.message.not_nil!.chat.id,
"text" => "Crystal is awesome but complicated",
}) # => Hash(String, Int32 | String)
But the constructor expects a Hash(Symbol | String, String | Bool | Int32 | Int64 | Float32 | Float64 | Nil)
.
These are diffferent types and cannot be magically casted. You'll need to ensure your payload has the correct type.
One way to do this is to explicitly declare the type of the hash literal:
Payload{
"chat_id" => update.message.not_nil!.chat.id,
"text" => "Crystal is awesome but complicated",
}
This is of course not great, but depending on your usecase it might be sufficient.
If you want to have a general interface that allows to receive any type of hash, you'll need to cast it to the Payload
type. This means copying the data into a new hash of that type:
def self.new(hash, method : String = "sendMessage")
payload = Payload.new
hash.each do |key, value|
payload[key] = value
end
new(payload, method)
end
For a real-world example, I am using this approach in Crinja to convert a number of different type variations to the matching ones.
Upvotes: 3