luau icon indicating copy to clipboard operation
luau copied to clipboard

Multiple table value types won't work when table type is part of union

Open ghost opened this issue 2 years ago • 5 comments

--!strict
local _value: {string | number}? = {"", 1}
TypeError: Type 'number' could not be converted into 'string'

ghost avatar Sep 05 '22 22:09 ghost

I also have this issue. I think (and I might be wrong here) it's because the type of a table literal is independent of the type annotation of the local variable.

When you create an expression {"", 1}, Luau tries to infer a type for it, but the type it infers is too strict. It infers {string} when it should be {string | number}, which causes the type error.

This is going off my own understanding though - this might be incorrect

JohnnyMorganz avatar Sep 05 '22 22:09 JohnnyMorganz

Question mark seems to trigger different behavior. Without it the warning disappears.

--!strict
local _value: {string | number} = {"", 1}

williamutbult avatar Oct 31 '22 15:10 williamutbult

I also get this error when trying this:

--!strict
local _value: {}? = {"", 1}

If you do it backwards, it doesn't accept a different data type other than a number.

2jammers avatar Jan 04 '23 22:01 2jammers

I'm working on a fix for this issue.

vegorov-rbx avatar Jan 06 '23 14:01 vegorov-rbx

Just including my experience with this problem, for reference.

--!strict

-- Errors happen only in strict mode. Apparently doesn't happen in non-strict,
-- but is also too lenient.

-- Table that can contain a mix of numbers and strings. Works.
type A = {number | string}

local function a(v:A)end

a({})
a({0})
a({""})
a({0,""})
a({"",0})

-- Table is included in a union. Fails.
type B = number | string | {number | string}

local function b(v:B)end

b(0)
b("")
b({})
b({0})
b({""})
b({0,""}) --> TypeError: Type 'string' could not be converted into 'number'
b({"",0}) --> TypeError: Type 'number' could not be converted into 'string'

-- Works when type of table is coerced.
b({0,""}::{number|string})
b({"",0}::{number|string})

-- Also fails for recursion.
type C = number | string | {C}

local function c(v:C)end

c(0)
c("")
c({})
c({0})
c({""})
c({0,""}) --> TypeError: Type 'string' could not be converted into 'number'
c({"",0}) --> TypeError: Type 'number' could not be converted into 'string'

-- Works when coerced to non-unioned table.
c({0,""}::{number|string})
c({"",0}::{number|string})

Anaminus avatar Aug 06 '23 11:08 Anaminus