Multiple table indexer types

I want something like this:

type Thing = ...

local _: Thing = {
    -- ok:
    [5] = 2,
    hello = workspace,

    -- not ok:
    [2] = "hello",
    foo = 5,
}

Number keys can only be numbers, and string keys can only be Instances.

I tried this:

--!strict
type Thing = {
	[number]: number,
} & {
	[string]: Instance
}

local _: Thing = {
	[5] = 2,
	hello = workspace
}

Unfortunately, this does not work:

TypeError: Type '_' could not be converted into '{number} & {| [string]: Instance |}'
caused by:
  Not all intersection parts are compatible.
Type '_' could not be converted into '{| [string]: Instance |}'
caused by:
  Property '[indexer key]' is not compatible.
Type 'number' could not be converted into 'string' in an invariant context

How do I do this? Is it possible?

I did a little test in studio, and found that if you replace the & in the type declaration bit with |, then it should work!

Doing this change basically changes it from an intersection to a union.

1 Like

While at first this did seem to fix the problem, this does not throw a type error (it should):

--!strict
type Thing = {
	[number]: number,
} | {
	[string]: Instance
}

local _: Thing = {
	[5] = 2,
	hello = 2  -- should error, but doesn't
}
}

It seems this just breaks the type checker entirely.