Skip to content
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

Autocomplete/Intellisense Does Not Show All Options For Object Value #17127

Closed
mjbvz opened this issue Jul 12, 2017 · 11 comments
Closed

Autocomplete/Intellisense Does Not Show All Options For Object Value #17127

mjbvz opened this issue Jul 12, 2017 · 11 comments
Labels
Bug A bug in TypeScript Design Limitation Constraints of the existing architecture prevent this from being fixed VS Code Tracked There is a VS Code equivalent to this issue

Comments

@mjbvz
Copy link
Contributor

mjbvz commented Jul 12, 2017

From @JonnyBoy333 on July 12, 2017 15:31

  • VSCode Version: 1.14.0
  • OS Version: macOS 10.12.5

Autocomplete/intellisense is not showing all the options for an object that goes into a function parameter even though it is defined in a typescript interface.

Example:

interface Fruit {
    /** Returns a fruit color. */
    getFruitColor(options: { fruit: 'apple' | 'orange' }): string;
    getFruitColor(options: { fruit: 'banana' }): boolean;
}

function testFunction (fruit: Fruit) {
    let color = fruit.getFruitColor({ fruit: '' }); // <-- Autocomplete only shows apple and orange as options and not banana
}

screen shot 2017-07-12 at 10 27 36 am

It appears that only the first method's options object is getting indexed by VS autocomplete but not the second one.

Reproduces without extensions: Yes

Copied from original issue: microsoft/vscode#30526

@mjbvz mjbvz self-assigned this Jul 12, 2017
@mjbvz mjbvz removed their assignment Jul 12, 2017
@mjbvz mjbvz added VS Code Tracked There is a VS Code equivalent to this issue and removed new release labels Jul 12, 2017
@mjbvz
Copy link
Contributor Author

mjbvz commented Jul 12, 2017

Here's the tsserver completions response:

[Trace  - 10:28:51 AM] Response received: completions (53). Request took 1 ms. Success: true 
Result: [
    {
        "name": "apple",
        "kind": "var",
        "kindModifiers": "",
        "sortText": "0"
    },
    {
        "name": "orange",
        "kind": "var",
        "kindModifiers": "",
        "sortText": "0"
    }
]

@JonnyBoy333
Copy link

@mjbvz Got it. Thanks for confirming this is Typescript related.

@mhegazy mhegazy added the Bug A bug in TypeScript label Aug 29, 2017
@mhegazy mhegazy assigned ghost Aug 29, 2017
@ghost ghost added the Design Limitation Constraints of the existing architecture prevent this from being fixed label Aug 31, 2017
@ghost
Copy link

ghost commented Aug 31, 2017

Unfortunately, this would be hard to fix in general.

When we get completions for a string literal directly inside a call expression, we have specialized code to iterate over every possible overload and get all string literals.

But when we get completions inside a string literal at an arbitrary location, we just call getContextualType and look for string literal types in there.

getContextualType will climb up to the signature and ask for its parameter types. Overload resolution will fail since { fruit: "" } is assignable to neither { fruit: "apple" | "orange" } nor { fruit: "banana" }, so we arbitrarily pick the first signature to get the contextual type.

To fix this in general would seem to require writing a getContextualTypes function that handled all overloads, returning all contextual types.

@mhegazy mhegazy closed this as completed Aug 31, 2017
@JonnyBoy333
Copy link

@andy-ms Thanks for taking a look at this. If this isn't something that's going to be looked at in the near future is there an approach you could recommend as a work around?

Right now I am having to choose between putting all the fruit types in the one getFruitColor method so that I can have autocomplete, but that is at the cost of having type safety on the return values. Or keeping it the way it is and having type safety, but only autocomplete on the arbitrary first signature. Obviously in my real use case there are quite a few more than three fruits and two return types, they are actually different fields on a form that can return different data types.

@ghost
Copy link

ghost commented Sep 5, 2017

@JonnyBoy333 I would recommend preferring correct types and no autocomplete over autocomplete and incorrect types, but that's just my opinion :P
You could also define a separate interface for each case and get autocomplete by explicitly annotating the type of the options:

interface RoundFruit {
    fruit: "apple" | "orange"
}
interface CurvedFruit {
    fruit: "banana"
}

function getFruitColor(fruit: RoundFruit): string;
function getFruitColor(fruit: CurvedFruit): boolean;

const options: RoundFruit = { fruit: "/*completions!*/" };
getFruitColor(options);

@wehrstedt
Copy link

I think this belongs to the same problem @andy-ms described above:

declare interface xyz {
     myVar: "value1" | "value2" | "value3"
}

And for this, you don't get any suggestions:

let y = getMyInterfaceObject(): xyz;
y.myVar  = "/*no completions*/";

Do you have any suggestions how to fix this or do I have to live with that for now?

@ghost
Copy link

ghost commented Sep 27, 2017

@wehrstedt You should be getting syntax errors there. You probably meant let y: xyz = getMyInterfaceObject();.

@wehrstedt
Copy link

Yep, sorry. I worte this piece of code in the comment field. But the issue is still the same. Any suggestions?

@ghost
Copy link

ghost commented Sep 27, 2017

It's working for me if y is really of type xyz. Could you share a complete example?

@wehrstedt
Copy link

unfortunately not.But I will try to complete the example:

This is my dts file:

declare namespace myNamespace {
	export interface myInterface {
		myVar: "value1" | "value2";
	}
}

declare var myInterface: myNamespace.myInterface;

I found out something interesting:
When I type

myInterface.myVar = "";

and hit CTRL + Space between the quotation marks in a typescript file, the code completion works. When I try the same in a js file, the code completion doesn't work.

This is probably the reason why the example above works for you. I'm developing javascript, not typescript. And for code completion I write some typescript definition files.

Is this behaviour correct?

@ghost
Copy link

ghost commented Sep 28, 2017

@wehrstedt You probably don't have both files included in the same project. If I use this tsconfig.json:

{
    "compilerOptions": {
        "module": "commonjs",
        "noEmit": true,
        "allowJs": true,
        "checkJs": true
    }
}

then I can get types from a .d.ts file applied to a .js file. But it looks like if we just see a .d.ts and .js file side-by-side with no tsconfig.json, we don't give you autocomplete. I've filed an issue at #18817.

@microsoft microsoft locked and limited conversation to collaborators Jun 14, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Bug A bug in TypeScript Design Limitation Constraints of the existing architecture prevent this from being fixed VS Code Tracked There is a VS Code equivalent to this issue
Projects
None yet
Development

No branches or pull requests

4 participants