Skip to content

Language Service not providing autocomplete on object literal in union type #3303

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
nycdotnet opened this issue May 29, 2015 · 4 comments
Closed
Assignees
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue

Comments

@nycdotnet
Copy link

Hi,

I'm not sure if this is possible or not, but neither VS 2015 RC with the TypeScript 1.5 beta plugin nor atom-typescript offer autocompletion in this example:

https://github.com/TypeStrong/typestrong-compiler/blob/35d8eb8662d9ad882ff29642fcb74191421d362c/typestrong-compiler.ts#L18-L19

If I remove either consoleOutput or actualVersion from the object literal passed to resolve, TypeScript will correctly complain. However, if I begin to type con or act to put those properties back, I don't get help. I'm assuming that this is because resolve() accepts ether T or Thenable<T> and perhaps the language service just gives up when it sees a union?

//cc: @basarat @mhegazy

If this is not fixable without going crazy, no big deal. The compiler is working correctly - it's just that the autocomplete experience could be better.

Thanks!

@RyanCavanaugh
Copy link
Member

Just to explain what's happening here: Completion here works based on the properties of the contextual type. Since T|Thenable<T> has no properties (because those types have no properties in common), we don't have anything to show you.

interface A {
    x1; y1; z1;
    m; n;
}
interface B {
    x2; y2; z2;
    m; n;
}

function fn(x: A|B) { }

image

However, if you changed resolve to be an overloaded function, and put the object type first, you'll see completion:

function fn(x: A);
function fn(x: B);
function fn() {}

image

That said, a union type is almost always a better choice than an overload set for single-argument functions, so it's probably not worth the trade-off.


We could probably do some hackery to show the union of all the properties of a union type for purposes of computing the completion list in the language service. In services.ts#2954 (in my copy):

                    let contextualTypeMembers = typeChecker.getPropertiesOfType(contextualType);
                    if (contextualTypeMembers && contextualTypeMembers.length > 0) {
                        // Add filtered items to the completion list
                        symbols = filterContextualMembersList(contextualTypeMembers, containingObjectLiteral.properties);
                    }

Instead of calling getPropertiesOfType, we could have some other function getCompletionPropertiesOfType that special-cased union types. It might be worth prototyping to see what the experience looked like.

@nycdotnet
Copy link
Author

Thanks for this very in-depth analysis, Ryan. Are you still on board with special-casing #1805? I know that's been somewhat dormant.

@mhegazy
Copy link
Contributor

mhegazy commented May 29, 2015

We could probably do some hackery to show the union of all the properties of a union type for purposes of computing the completion list in the language service. In services.ts#2954 (in my copy),
Instead of calling getPropertiesOfType, we could have some other function getCompletionPropertiesOfType that special-cased union types. It might be worth prototyping to see what the experience looked like.

I believe this is the correct approach. In the consumption case, you never want the union properties, you just want the properties of one of the union type constituents. showing only union properties is not helpful. since we do not know which one of the union type constituents you want, the next best thing is to give the user all options and let them decide. I have meant to add that a while back but got distracted by other issues.

@mhegazy mhegazy added the Bug A bug in TypeScript label May 29, 2015
@mhegazy mhegazy added this to the TypeScript 1.6 milestone May 29, 2015
@mhegazy mhegazy self-assigned this May 29, 2015
@mhegazy mhegazy assigned DanielRosenwasser and unassigned mhegazy Jul 1, 2015
@DanielRosenwasser
Copy link
Member

Looks like it's fixed by #3615 but I'll add a test case.

@DanielRosenwasser DanielRosenwasser added the Fixed A PR has been merged for this issue label Jul 1, 2015
@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue
Projects
None yet
Development

No branches or pull requests

4 participants