A little issue encountered in union type reference for NamedTuple

when i was reading the specification of union types(Union types - Crystal),i found that the specification says the typeof(t3) will be NamedTuple(x: Int32 | Nil, y: String | Bool)

codes are:

t1 = {x: 1, y: "hi"}   # Tuple(x: Int32, y: String)
t2 = {y: true, x: nil} # Tuple(y: Bool, x: Nil)

t3 = rand < 0.5 ? t1 : t2
typeof(t3) # NamedTuple(x: Int32 | Nil, y: String | Bool)

I ran this snippet of codes but i got:


although this is not some big problem, i can’t help to figure out why the union type was not the same as spesification says.

also,according to the specification,the order of the keys will be the ones from the tuple on the left hand side, do the types of keys do the same?
I did another test that modified the codes to this:


The type of x is String | Nil but i expected it would be Nil | String
I guess there must be something fundamental that i do not know.

The output in the spec examples is incorrect.

The union Bool | String and String | Bool is the same type. When showing a union type, the compiler sorts the types alphabetically, that’s why you get Bool | String. But showing String | Bool in the spec is the same.

according to the specification,the order of the keys will be the ones from the tuple on the left hand side

That’s correct! In your second example you have a union that’s formed by t2 (y, x) and t1 (x, y) so x, y wins. But in general the order doesn’t matter for a named tuple, so we should probably remove that from the spec. It’s just an implementation detail.

I guess there must be something fundamental that i do not know

Yes! It’s the fact that T | U is the same as U | T, as I explained above :slight_smile:

In practice, none of this matters for a language user. They are just implementation details.

There’s simply a special rule that Nil is always printed as the last type of a nilable union. The reason the special nature of Nil and that it’s the most common type in a union. Showing it always as last type helps developer awareness.

2 Likes

Thanks for your immediate response and your answer! I been reading the spec nowadays, using the rules i learned in Type reference i tried to speculate the union types of Tuple then i got that small question(now it is solved)

Got it, thanks for answering! So i guess the Nil type would always be the last one if a union has it and it will not be sorted by compiler in terms of alphabetic. Is that correct?

1 Like

Yes, exactly. You can see the implementation here:

Really neat and demonstrating.

The “order of the keys” refers to the fact that y: appears before x: in the returned type.