Reputation: 15336
Why NamedTuple of the same type are not compatible?
alias Data = NamedTuple(
title: String?
)
data : Data = { title: nil } # Explicitly specifying that
# it has ` : Data` type
proc = ->(data : Data){ p data }
proc.call data # And yet it says it's not
# of `Data` type
Error
Error: type must be NamedTuple(title: String | Nil), not NamedTuple(title: Nil)
Upvotes: 1
Views: 90
Reputation: 5661
Your assumption is incorrect: data : Data
restricts the type of the local variable to Data
(which is an alias for NamedTuple(title: String | Nil)
). This type restriction does not affect the value assignment on the right hand side. The literal value {type: nil}
is typed as NamedTuple(title: Nil)
. This type is compatible with the type restriction to Data
, so it can be assigned to the variable.
This implicitly covariant type restriction does not apply with proc types. I'm not sure about the reasoning behind that. It seems that this should be able to work. So maybe it just needs to be implemented.
You can however explicitly cast NamedTuple(Nil)
to NamedTuple(String | Nil)
:
alias Data = NamedTuple(
title: String?
)
data = { title: nil }.as(Data) # Cast named tuple to Data
proc = ->(data : Data){ p data }
proc.call data
However, it is usually not a good idea to work with named tuples as regular data types. They are only recommended for very specific use cases such as named arguments. Defining custom structs (for example using the record macro) is a better idea and gives you a more powerful and flexible data type. I'd implement your example like this:
record Data,
title : String?
data = Data.new(title: nil)
proc = ->(data : Data){ p data }
proc.call data
Upvotes: 2