Search code examples
crystal-langunion-types

Declaring union types with nil in Crystal


I've been following the official documentation of Crystal but I couldn't find any details on this. The regular syntax when declaring a union type is String | Int32. However, I've noticed a difference regarding the Nil type.

The regular way of declaring the union still works:

def foo(id : String | Nil)
end

# Overloads are:
#  - foo(id : String | Nil)

However I've also seen a shortened syntax which I couldn't find any documentation for:

def foo(id : String?)
end

# Overloads are:
#  - foo(id : String | ::Nil)

The result is almost exactly the same except Nil if prefixed with 2 colons. My guess that this is something related to the global scope of Nil as I've seen a similar syntax in other languages.

  1. Is String | Nil and String? the same thing, and when should you use one vs the other?
  2. What's the meaning of 2 colons in the type signature (e.g. ::Nil)?

Solution

    1. yes, they're exactly the same, people typically use the Foo? version as it's shorter.

    2. ::Nil means "the class Nil at the root namespace". This means that if you define a different Nil class in a different namespace, ::Nil always refers to the nil in the stdlib.