microsoft / microsoft/TypeScript

Can we cut down on `Object.assign` overloads?

Open
#28,323 5 comments 5 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Needs Proposal Suggestion
Dominant language
Go
Stars
111k
Forks
14.3k
Avg merge
2d 4h
Merged PRs (30d)
132

Description

We can convert unions into intersections (thanks @jcalz!), and we can model variadic args pretty well, so I figured I'd try to model Object.assign with a single overload. Here's what I came up with:

// Maps elements of a tuple to contravariant inference sites.
type MapContravariant<T> = {
    [K in keyof T]: (x: T[K]) => void
}

type TupletoIntersection<T, Temp = MapContravariant<T>> =
    // Ensure we can index with a number.
    Temp extends Record<number, unknown>
        // Infer from every element now.
        ? Temp[number] extends (x: infer U) => unknown ? U : never
        : never;

declare function assign<T extends object, Rest extends object[]>(
    x: T,
    ...xs: Rest
): T & TupletoIntersection<Rest>;

Unfortunately this doesn't quite give the right results on the following:

let asdf = assign({x: "hello"}, Math.random() ? {x: "hello"} : {z: true });

Currently the type of asdf is:

| ({ x: string; } & { x: string; z?: undefined; })
| ({ x: string; } & { z: boolean; x?: undefined; })

What a beautiful type! Unfortunately you can see that the second element of the union tries to intersect types with conflicting properties for x which is nonsense.

Additionally, @weswigham pointed out that this really won't work for the case where you started off with just a plain array whose elements are eventually spread into Object.assign.

I do wonder if there's anything better we can do here.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

The issue names no files, tests, or entry points. Start by reproducing the proposed assign typing and the union and spread-array examples from the issue, then trace the existing Object.assign modeling in the TypeScript type checker and standard library declarations. Done means a reviewed approach that handles these cases without conflicting intersections.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
20/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.