Enum types don't refine correctly in if/else statements

Reproduction Steps

Create a new place, copy this source code into a script:

Source Code
--!strict

local function f(e: "foo"|"bar"|"baz")
	if e == "foo" then
		local v: "foo" = e;
	elseif e == "bar" then
		local v: "bar" = e;
	else
		local v: "baz" = e;
	end
end

local function g(e: number|string|boolean)
	if type(e) == "number" then
		local v: number = e;
	elseif type(e) == "string" then
		local v: string = e;
	else
		local v: boolean = e;
	end
end

Expected Behavior

I’d expect the type of argument e of function f to be of type “baz” after the two type refinements.

Actual Behavior

It is instead of type "foo"|"bar"|"baz".

I also included an equivalent function that shows the behavior with non-enum intersection types, namely, number|string|boolean, which works as expected.

RobloxStudioBeta_vMQbqhH4Su

Also, I think this might be a more general problem where the enum cannot narrow via a negative case. You can get similar results with assertions.

RobloxStudioBeta_HWjRtCAWGy

Workaround

Use any type liberally. Or be explicit about the last else clause.

Issue Area: Engine
Issue Type: Other
Impact: Moderate
Frequency: Rarely

Thanks for the report! We’ll investigate.

1 Like