Type checker losing track of intersection part of a type when used as a table field

I have some structures with unions and intersections that I am trying to type check and ensure exact equality. However for some reason when I put these types into a table type (like Z1/Z2) the equality check fails, whereas comparing them directly (M1/M2) the equality check succeeds.

type A1 = {a: true}
type B1 = {b: true}
type C1 = {c: true}
type M1 = A1 & (B1 | C1)

type A2 = {a: true}
type B2 = {b: true}
type C2 = {c: true}
type M2 = A2 & (B2 | C2)

type Z1 = {
	E: {[string]: M1};
}
type Z2 = {
	E: {[string]: M2};
}
	
local Z: Z1 = nil

-- These two lines have type errors:
local Checked: Z2 = Z
Checked = Z :: Z2

The error I am getting on the first line is:
Type '(B1 | C1) & A1' could not be converted into 'B2 | C2'; none of the union options are compatible.
It looks like the A2 type is being lost track of.

The error I get on the second line is:
Cannot cast Z1 into Z2 because the types are unrelated.

Here’s the full message for this first one:


What seems to be the same issue can also be demonstrated with a more concise example:

type A = {Y: boolean}
type C = A & {X: {b: boolean} & {c: boolean}}
local V: C = {
	Y = true;
	-- Get an error about extra field 'c', the type checker only sees {b: boolean}.
	X =  {b = true, c = true};
}

Thanks for the report!

We’ve been hard at work on a refresh of the type solver that will fix this issue.

1 Like