Current limitations of union types
In the current version, there are two main limitations regarding support for union types in Teal.
The first one is that the is
operator always matches a variable, not arbitrary
expressions. This limitation is there to avoid aliasing.
The second one is that Teal only accepts unions over a set of types that
it can discriminate at runtime, so that it can generate code for the
is
operator properly. That means we can either only use one table
type in a union, or, if we want to use multiple table types in a union,
they need to be records or interfaces that were declared with a where
annotation to discriminate them.
This means that these unions not accepted:
local invalid1: {string} | {number}
local invalid2: {string} | {string:string}
local invalid3: {string} | MyRecord
However, the following union can be accepted, if we declare the record
types with where
annotations:
local interface Named
name: string
end
local record MyRecord is Named
where self.name == "MyRecord"
end
local record AnotherRecord is Named
where self.name == "AnotherRecord"
end
local valid: MyRecord | AnotherRecord
A where
clause is any Teal expression that uses the identifier self
at most once (if you need to use it multiple times, you can always write
a function that implements the discriminator expression and call that
in the where
clause passing self
as an argument).
Note that Teal has no way of proving at compile time that the set of where
clauses in the union is actually disjoint and can discriminate the values
correctly at runtime. Like the other aspects of setting up a Lua-based
object model, that is up to you.
Another limitation on is
checks comes up with enums, since these also
translate into type()
checks. This means they are indistinguishable from
strings at runtime. So, for now these are also not accepted:
local invalid4: string | MyEnum
local invalid5: MyEnum | AnotherEnum
This restriction on enums may be removed in the future.