Luau typechecking failing with intersections on complex types

Sometimes when using complex luau types that are built up of many sub-types and intersections the script editor will highlight the problem variable as being unable to convert/cast etc.

This could result from a misunderstanding on my end, but I’ve shared my example case w/ a few people and they too can’t really figure out what’s going on.

For example, say my type definitions are like so:

--!strict

type PetsOriginMandatory = {
	year: number,
}

type PetsOriginOptional = {
	example: string?,
}

type PetsOrigin = PetsOriginMandatory & PetsOriginOptional

type PetsMandatory = {
	origin: PetsOrigin,
	model: string,
}

type PetsOptional = {
	is_egg: boolean?,
}

type Pets = PetsMandatory & PetsOptional

When I try to use these definitions the script editor yells at me:

local function methodTakesPets(pets: { [string]: Pets })
	
end

-- incorrect failure and unhelpful error:
methodTakesPets({
	["cat"] = {
		model = "Cat",

		origin = {
			year = 2019,
			example = "test",
		},

		is_egg = false,
	},
})

-- incorrect failure and unhelpful error:
local cat = {
	model = "Cat",

	origin = {
		year = 2019,
		example = "test",
	},

	is_egg = false,
} :: Pets

-- incorrect failure and helpful but incorrect error:
local cat: Pets = {
	model = "Cat",

	origin = {
		year = 2019,
		example = "test",
	},

	is_egg = false,
}

Also, in the above when I say “unhelpful error” I mean that when hovering the error provided by luau doesn’t actually give me any useful information that I could use to fix the perceived issue.

For example:

As far as I can tell the issue seems to be that the origin table can’t seem to match up with the origin type because of something to do with intersections.

I can get it to work if:

  • the origin type is combined manually instead of using intersection types
  • or the Pets type is combined manually instead of using intersection types
  • or the origin table is typecasted with :: PetsOrigin

However, I’m not super keen on using typecasting if it’s not going to work properly in all circumstances.

1 Like

This needs read/write properties (see the RFC) to be able to decide whether this subtyping is valid. We’re working on the new type checking architecture, and that new architecture plus readonly properties will help to fix this without the need for casts.

1 Like