String constants lose type info when being cast to an intersection type

Reproduction Steps

Copy/paste this script into a blank place:

Source Code
--!strict

--Use of "ShapeType" field allows me to discriminate the kind of shape in a function which simply takes
--a Shape argument.
type Square = {ShapeType: "Square"} & {Size: number};
type Rectangle = {ShapeType: "Rectangle"} & {Width: number; Height: number};
type Circle = {ShapeType: "Circle", Radius: number};
type Shape = Square | Rectangle | Circle;

--[[

Type Error: (19,1) Type 's' could not be converted into '{| ShapeType: "Square" |} & {| Size: number |}'
caused by:
  Not all intersection parts are compatible. Type 's' could not be converted into '{| ShapeType: "Square" |}'
caused by:
  Property 'ShapeType' is not compatible. Type 'string' could not be converted into '"Square"'

--]]
local s: Square = {
	ShapeType = "Square";
	Size = 4;
};

--I can suppress the error by casting the string constant into itself. *Weird*.
local r: Rectangle = {
	ShapeType = "Rectangle" :: "Rectangle";
	Width = 5;
	Height = 3;
};

--Circle doesn't have this problem because it isn't a union type. This is a toy example, but in my
--real use-case, making the type a union helps cut away a lot of boilerplate & avoid copy/paste
--errors, as one of the types is a template.
local c: Circle = {
	ShapeType = "Circle";
	Radius = 8;
};

Expected Behavior

I shouldn’t get a type error.

Actual Behavior

I get a type error.

You can see the type checker is only angry about how I cast to the Square type:



Workaround

You can workaround the issue by casting the string constant to itself, as demonstrated with the “Rectangle” type in the above screenshot. And as always, you can cast to any to suppress the warnings, but then you lose type checking on that field.

You can also avoid type intersections that involve string constants to fix the problem, but that’s a lame solution.

Issue Area: Studio
Issue Type: Other
Impact: Low
Frequency: Sometimes

Thanks for the report. I filed a ticket to our internal database and i’ll come back with updates when available.

1 Like

Hello! Sorry for the late response here.

We’ve been hard at work on a refresh of the type solver. It’s not quite ready for prime time yet, but I’ve verified that it fixes this issue.