Skip to content

Type guard doesn't work properly with unions #742

Closed
@RobertBouillon

Description

Type guards with unions that include a record (table) will only check for the table. Other values included in the union will not be captured.

global record Foo
  bar : string
end

global function repro(x:Foo|string|nil) : integer
  local y = x
  if y is string | Foo then
    return 1
  elseif y is nil then
    return 2
  end
  return 3 -- string falls through here!
end

print(repro({} as Foo)) --1
print(repro("1"))       --3
print(repro(nil))       --2

Workaround

You can add a manual type guard in place of the union, which then gets inferred, but only if:

  1. it's in an elseif block and
  2. the if statement starts with an is expression
global function repro(x:Foo|string|nil) : integer
  local y = x
  if y is nil then
    local z : nil = y 
    return 2
  elseif type(y) == "table" or type(y) == "string" then
    local z : Foo | string = y
    return 1
  end
  return 3 --No fall through
end

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions