Skip to content

Fix/object assign non table source (#1642)#1710

Merged
Perryvw merged 2 commits into
TypeScriptToLua:masterfrom
RealColdFry:fix/object-assign-non-table-source
Apr 16, 2026
Merged

Fix/object assign non table source (#1642)#1710
Perryvw merged 2 commits into
TypeScriptToLua:masterfrom
RealColdFry:fix/object-assign-non-table-source

Conversation

@RealColdFry
Copy link
Copy Markdown
Contributor

Fixes #1642

Issue playground link

Minimal repro playground link, copied below:

const obj = { key: 1 };                                                                                                                      
const b = { ...(1 < 0 && obj) };                                                                                                             
console.log(b); // expected: {}                                                                                                              

{ ...(cond && obj) } is a common idiom: when cond is falsy, the spread short-circuits to false and JS treats it as a no-op (Object.assign coerces primitives to wrapper objects with no own enumerable properties). TSTL's __TS__ObjectAssign didn't guard against non-table sources, so pairs(false) errored at runtime.

Lualib comp

Old

local function __TS__ObjectAssign(target, ...)
    local sources = {...}
    for i = 1, #sources do
        local source = sources[i]
        for key in pairs(source) do
            target[key] = source[key]
        end
    end
    return target
end

New

local function __TS__ObjectAssign(target, ...)
    local sources = {...}
    for i = 1, #sources do
        local source = sources[i]
        if type(source) == "table" then
            for key in pairs(source) do
                target[key] = source[key]
            end
        end
    end
    return target
end

`{ ...(cond && obj) }` short-circuits to `false` when `cond` is falsy. JS
treats this as a no-op (Object.assign coerces primitives to wrapper objects
with no own enumerable properties), but `__TS__ObjectAssign` was iterating
every source unconditionally, so `pairs(false)` errored at runtime.

Skip non-table sources, matching the spec for null/undefined/primitive args.
Invert the type guard so it nests the spread loop instead of using `continue`,
which lowered to a `repeat ... until true` + `break` dance. Same behavior,
the bundled helper now reads like the hand-written original.
@RealColdFry RealColdFry marked this pull request as ready for review April 16, 2026 12:52
@RealColdFry RealColdFry changed the title Fix/object assign non table source Fix/object assign non table source (#1642) Apr 16, 2026
@Perryvw Perryvw merged commit c3b3a8b into TypeScriptToLua:master Apr 16, 2026
5 checks passed
@RealColdFry RealColdFry deleted the fix/object-assign-non-table-source branch April 22, 2026 01:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Encountered error with { ...(bCheck && obj) }

2 participants