luau icon indicating copy to clipboard operation
luau copied to clipboard

never type refinement on optional intersection type

Open cheesycod opened this issue 7 months ago • 1 comments

--!strict

export type Foo = {
    foo: string,
}

export type Bar = Foo & {
    copy: (...any) -> any
}

export type Baz = Foo & {
    stats: () -> any
}

export type Executor = {
    bar: Bar?, 
    baz: Baz?,
    [string]: Foo?
}

local function new(): Executor
    return {}
end

local function _test() 
    local nd = new() 
    local bar = nd.bar
    if not bar then 
        return 
    end
    print(bar)
end

bar in the end, if you hover over it, is never and not the expected Bar table type

cheesycod avatar May 01 '25 02:05 cheesycod

I think I just ran into this issue, but with some slightly more interesting behavior:

--!strict

type Item = {
	name: string,
	dateInserted: number,
}

local items: {Item} = {}

local function getLatestItem(): Item?
	local latestItem = nil -- line 11

	for _, item in items do
		if latestItem == nil then
			latestItem = item
			continue
		end

		if item.dateInserted > latestItem.dateInserted then -- line 19
			latestItem = item
		end
	end

	return latestItem
end

this is (hopefully) some reasonable code, which is an interesting case for the solver. It must (and does correctly) infer that the type of latestItem is Item?, however on line 19 latestItem incorrectly becomes never, making this a silent fail.

What is interesting is that manually annotating latestItem (on line 11) to be local latestItem: Item? = nil makes this case work.

OverHash avatar Jun 30 '25 04:06 OverHash