Hello, I need a variable of type
Class and I found the following behaviors:
I can do this:
puts typeof(Bool | Int32 | Int64 | String)
# => (Bool | Int32 | Int64 | String).class
but not this (why?):
c : typeof(Bool | Int32 | Int64 | String) = Bool
# => Error: type must be (Bool | Int32 | Int64 | String).class, not Bool.class
also I can do this:
c : Bool.class | Int32.class | Int64.class | String.class = Bool
puts typeof(c) # => Class (!!!)
puts c # => Bool
Look at this!
typeof(c) is Class (so, union of several Classes is aggregated to the Class and it works)!
but I can’t do this:
c : Class = Bool
# => Error: can't use Object as the type of a variable yet, use a more specific type
Class as type directly - but look at example above, when union is aggregated to the
Is this OK?
I’m really wondering what’s your use case
We have dozens of “Entity” classes and we need to store some internal metadata about relations etc., so we need an attribute (instance variable) with type “Class” to point to our relation class.
It’s not about use case - it’s just an instance variable (or simple variable) that stores Class - simple.
And that work with Classes is a little strange as you can see.
The type of a union of classes is different than the union of classes.
c : typeof(Bool | Int32 | Int64 | String)
the only thing you can assign is
Bool | Int32 | Int64 | String, while in:
c : Bool.class | Int32.class | Int64.class | String.class
you can assign any of
I think in the past both types were equal or resolved to a same time and I think we changed that because it was unsound (I can’t remember why).
Then you get
Class for asking the type of a class (like
Bool.class). There’s a PR to change that so that
typeof(Bool.class) gives you
Bool:Class:Class but we are not sure it’s the right thing to do: https://github.com/crystal-lang/crystal/pull/7255
In your case you probably need to use the
Bool.class | Int32.class approach, but maybe showing some more code for what you want/need might be better.