microsoft / microsoft/TypeScript

Improve Javascript intellisense type inference for cases where Object.assign(this, ...) is used with an object with known type information

Open
#16,163 7 comments 23 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Awaiting More Feedback Domain: JavaScript Suggestion VS Code Tracked
Dominant language
Go
Stars
111k
Forks
14.3k
Avg merge
2d 4h
Merged PRs (30d)
132

Description

From @jj101k on May 28, 2017 10:16

  • VSCode Version: 1.12.2 (19222cdc84ce72202478ba1cec5cb557b71163de)
  • OS Version: macOS Sierra 10.12.5 (16F73)

Given the Javascript code:

class Foo {
    constructor() {
        Object.assign(
            this,
            {
                bar: "abc",
            }
        );
        this.foo = "def";
    }
}

var f = new Foo();
console.log(f.foo);
console.log(f.bar);

If you hover over f.foo, it will tell you that it's a string. If you hover over f.bar, it will say it's "any". They should both say "string".

Object.assign is a fairly common way of setting several properties with a bit less copy/paste. In cases where an object without known type information is used as the last argument it isn't possible to statically infer appropriate types for the modified object ("this", here) and equivalently the object that Object.assign returns. Where type information of the last argument is known, it is safe and appropriate to import all of that into the type information for the object, as if a series of direct assignments had been done.

Caveats: In Javascript (perhaps not Typescript) it's possible that further unknown properties are present on any given object, so it would be appropriate to void all inferred type information which is not between Object.assign and the end of the constructor. If Object.assign is used outside a constructor (on a named object) it should void all inferred types entirely, because the type information could be entirely different before and after. The same should be true if Object.assign is conditionally called in the constructor. The only exception should be when all arguments after the first have known final type information, eg. an immediate object.

For practical purposes, Object.assign(foo, bar, {baz: 1}) should be considered equivalent to for(name in bar) if(bar.hasOwnProperty(name)) foo[name] = bar[name]; foo.baz=1;.

Copied from original issue: Microsoft/vscode#27397

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

Start by reproducing the provided JavaScript class and Object.assign example in the TypeScript checker or editor tooling, then trace how the known type of the final argument is handled. Done means hovering over both f.foo and f.bar reports string while preserving the documented caveats for unknown, conditional, or later assignments.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, typescript
Domain
compilers
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.