The Crystal Programming Language Forum

Weird type checking

Hello! Please, look at this sample code, errors occurs at 2 lines at the end and I am really confused, why… What is the differnece between “a” and “a2”+“a3”? Thanks!

def all_relation_transformer_classes                                                                                                                                                                                                       
  {{RelationTransformer.subclasses}}
end

class RelationTransformer
end

class PowerConnectionRelationTransformer < RelationTransformer
end

a : Array(RelationTransformer) = Array(RelationTransformer).new
a << PowerConnectionRelationTransformer.new
pp a # OK

a2 : Array(RelationTransformer) =  all_relation_transformer_classes.map { |rtc| rtc.new } # error
a3 : Array(RelationTransformer) = Array{PowerConnectionRelationTransformer.new} # error
# both errors are: Error: type must be Array(RelationTransformer), not Array(PowerConnectionRelationTransformer)

When you create an array of just PowerConnectionRelationTransformer it’s inferred as Array(PowerConnectionRelationTransformer) which is not compatible with Array(RelationTransformer).

It’s the most common thing people are surprised about when using Crystal, so don’t worry.

If you search for “array covariance” or something like that in the GitHub issues or here in the forums you’ll find a ton of these discussions.

In your case you probably want to do [PowerConnectionRelationTransformer.new] of RelationTransformer or array.map(&.as(RelationTransformer))

Understand. I try to use “not_nil!” and “as” (…) methods as little as possible, I don’t like it very much, but OK, I have to go further…

Thanks!