luau
luau copied to clipboard
Nested tagged unions do not work as I want them to work
type CircularEntity = {
shape: 'Circular',
only_for_circular: any,
}
type RectangularEntity = {
shape: 'Rectangular',
}
type Entity = CircularEntity | RectangularEntity
local entity: Entity = {} :: any
if entity.shape == 'Circular' then
print(entity.only_for_circular) -- OK ✅
end
if entity.shape == 'Rectangular' then
print(entity.only_for_circular) -- Warning ✅
end
in the above case , tagged unions work as expected . in the implementation below , they do not :
type CircularEntity = {
parameters: {
shape: 'Circular',
only_for_circular_inside: any,
},
only_for_circular: any,
}
type RectangularEntity = {
parameters: {
shape: 'Rectangular',
},
}
type Entity = CircularEntity | RectangularEntity
local entity: Entity = {} :: any
if entity.parameters.shape == 'Circular' then
print(entity.only_for_circular) -- Warning ❌
print(entity.parameters.only_for_circular_inside) -- OK ✅
end
if entity.parameters.shape == 'Rectangular' then
print(entity.only_for_circular) -- Warning ✅
print(entity.parameters.only) -- Warning ✅
end
here is my ideal use case :
type DamageModel = ModelCommon & {
modifier: {
Value: 'Damage',
},
damage_part: Part,
}
type HealModel = ModelCommon & {
modifier: {
Value: 'Heal',
},
}
type ModelCommon = Model & {
modifier: StringValue,
}
type MyModel = DamageModel | HealModel
local model: MyModel = {} :: any
if model.modifier.Value == 'Damage' then
print(model.damage_part) -- Warning
end
i have to do this since there is no typechecking for attributes , perhaps if there is a way to accomplish this , i'll be thankful if you let me know .
for attributes you could make it work like this :
type HealingButton = ButtonCommon & {
GetAttribute:
((ButtonCommon, "Class") -> ('Healing')),
health: IntValue,
}
type DamageButton = ButtonCommon & {
GetAttribute:
((ButtonCommon, "Class") -> ('Damage')),
damage: IntValue,
}
type ButtonCommon = Model & {}
type Button =
HealingButton |
DamageButton
local button: Button = {} :: any
-- Type Error: (24,4) Cannot call non-function (((Instance, string) -> any) & ((Model, "Class") -> "Damage")) | (((Instance, string) -> any) & ((Model, "Class") -> "Healing"))
if button:GetAttribute("Class") == 'Damage' then
-- Type Error: (26,8) Key 'damage' is missing from 'Model & {| |} & {| GetAttribute: (Model, "Class") -> "Healing", ... 1 more ... |}' in the type '(Model & {| |} & {| GetAttribute: (Model, "Class") -> "Damage", ... 1 more ... |}) | (Model & {| |} & {| GetAttribute: (Model, "Class") -> "Healing", ... 1 more ... |})'
print(button.damage)
end