Union types

    At the end of the if, will have the Int32 | String type, read “the union of Int32 and String”. This union type is created automatically by the compiler. At runtime, a will of course be of one type only. This can be seen by invoking the class method:

    1. # The runtime type
    2. a.class # => Int32

    The compile-time type can be seen by using typeof:

    A union can consist of an arbitrary large number of types. When invoking a method on an expression whose type is a union type, all types in the union must respond to the method, otherwise a compile-time error is given. The type of the method call is the union type of the return types of those methods.

    1. # to_s is defined for Int32 and String, it returns String
    2. a.to_s # => String
    3. a + 1 # Error, because String#+(Int32) isn't defined

    In the general case, when two types T1 and T2 are combined, the result is a union T1 | T2. However, there are a few cases where the resulting type is a different type.

    If T1 and T2 are under the same hierarchy, and their nearest common ancestor is not Reference, Struct, Int, Float nor Value, the resulting type is Parent+. This is called a virtual type, which basically means the compiler will now see the type as being Parent or any of its subtypes.

    For example:

    1. end
    2. class Bar < Foo
    3. end
    4. class Baz < Foo
    5. bar = Bar.new
    6. baz = Baz.new
    7. # Here foo's type will be Bar | Baz,
    8. # but because both Bar and Baz inherit from Foo,
    9. # the resulting type is Foo+
    10. foo = rand < 0.5 ? bar : baz
    11. typeof(foo) # => Foo+

    For example:

    The union of two named tuples with the same keys (regardless of their order) results in a named tuple type that has the union of the types in each key. The order of the keys will be the ones from the tuple on the left hand side.

    For example:

    1. t1 = {x: 1, y: "hi"} # Tuple(x: Int32, y: String)
    2. t2 = {y: true, x: nil} # Tuple(y: Bool, x: Nil)
    3. t3 = rand < 0.5 ? t1 : t2
    4. typeof(t3) # NamedTuple(x: Int32 | Nil, y: String | Bool)