Typescript: Better IntelliSense for TypeScript/JavaScript

Created on 9 May 2016  ·  11Comments  ·  Source: microsoft/TypeScript

_From @donaldpipowitch on May 4, 2016 6:16_

  • VSCode Version: 1.0.0
  • OS Version: OS X 10.11.4

I think IntelliSense could show more documentation than it currently does. Take the following example (concrete feature requests are marked with a leading "❤️"):

/**
 * Add numbers!
 * @param a First number.
 * @param b Second number.
 */
function add(a: number, b: number): number {
  return a + b;
}

/**
 * This is a.
 */
const a = 1;

const c = add(a, 2);

/**
 * This is some object.
 */
interface SomeObject {
  /**
   * This is foo.
   */
  foo: string;
  /**
   * This is bar.
   */
  bar: string;
}

/*
 * This is an instance of some object.
 */
const someObject: SomeObject = {
  /**
   * Test.
   */
  foo: 'foo',
  bar: 'bar'
};

const foo2 = someObject.foo;

And now let us step through each statement and look if it could be improved.

1. Function signature

function add(a: number, b: number): number {
  • Hovering over add shows Add numbers!.
  • Hovering over a shows First number..
  • Hovering over b shows Second number..

Great. Everything works 👍

2. Function body

  return a + b;
  • Hovering over a shows First number..
  • Hovering over b shows Second number..

Great. Everything works 👍

3. Variable declaration

const a = 1;
  • Hovering over a shows This is a..

Great. Everything works 👍

4. Function call

const c = add(a, 2);
  • Hovering over c shows nothing.

    • This is expected. We have no description like for const a.

    • ❓ However... it doesn't seem we can document return values from a function call properly. Adding * @return This is the sum. to the function add documentation shows the return annotation as part of the description. But it would be nice, if hovering over c would show This is the sum. instead.

    • If we'd add a description to const c like we did for const a (e.g. This is c.) _and_ we add a proper @return annotation to function add it would be nice if IntelliSense would show _both_ description when hovering over c: This is c. and This is the sum. (maybe with a small visual delimiter between both descriptions.).

  • Hovering over add shows Add numbers!.
  • Hovering over a shows This is a..

    • It would be nice, if it would also show First number..

  • Hovering over 2 shows nothing.

    • It would be nice, if it would show Second number..

❤️ Request 1: It would be nice to show @return annotations correctly in IntelliSense.
❤️ Request 2: It would be nice to _additionally_ show @param and @return annotations alongside with descriptions of variable declarations or _at least_ as a fallback, if a variable has no _own_ description.

5. Interface

interface SomeObject {
  • Hovering over SomeObject shows This is some object..

Great. Everything works 👍

6. Property in interface

  foo: string;
  • Hovering over foo shows This is foo..

Great. Everything works 👍

7. Object with interface

const someObject: SomeObject = {
  • Hovering over someObject shows nothing.

    • I'd expect to see This is an instance of some object..

  • Hovering over SomeObject shows This is some object..

❤️ Request 3: It would be nice to show the description of an object using an interface.

8. Properties of an object with interface

  foo: 'foo',
  bar: 'bar'
  • Hovering over foo shows Test..

    • It could also show This is foo..

  • Hovering over bar shows nothing.

    • It could at least show This is bar..

❤️ Request 4: It would be nice to _additionally_ show property descriptions from an interface _and_ descriptions of properties in a concrete object or _at least_ as a fallback, if the property of an object has no _own_ description.

9. Using properties of an object with interface

const foo2 = someObject.foo;
  • Hovering over foo shows This is foo..

    • It could also show Test.. (💡 This was very surprising for me that IntelliSense used This is foo. instead of Test. here. However... best thing would be to show both.)

  • Hovering over foo2 shows nothing.

    • It looks like the the type is correctly inferred and it would be nice if the descriptions could be reused here, too. (E.g. Test. and This is foo.)

  • Hovering over someObject shows nothing.

    • It should show This is an instance of some object. (and could additionally show This is some object.).

❤️ Request 5: When using properties of an object which are documented in the object itself _and_ in the interface it would be nice if the description from the object declaration could be shown (because it is probably more custom to the current use case) _or_ show both descriptions.
❤️ Request 6: When types can be inferred it would be nice to infer descriptions, too.

_Copied from original issue: Microsoft/vscode#6083_

API Out of Scope Suggestion VS Code Tracked

Most helpful comment

There's one more thing that's been a bit lacking with IntelliSense. When a variable is to be of a certain interface and we are defining that object, there are no initial suggestions for the Object's keys until you type the first character -- even if you force-show autocomplete. When I'm defining an object from scratch and I don't remember what other keys it has defined it's been driving me nuts as I have been basically manually iterating through "a", "b", "c", "d"... initial letters to see what other keys I might have forgotten about. This is a problem especially in those times when the type is implicitly inferred and I can't simply CTRL+hover it to see it's declaration. Here's what I mean:

interface Human {
  firstName: string;
  lastName: string;
  age: number;
}

let me: Human = { ... } // <---- when typing inside it would be great to see autocomplete for the properties even BEFORE we type the first letter
// even more annoying when type of 'me' is inferred

All 11 comments

_From @rozzzly on May 5, 2016 3:45_

I'd like to see the hover tooltip get a bit of a makeover. I've been playing around with the extension api, but hover providers are pretty limited. It would be awesome if you could pass html, not just a MarkedString. I'm imagining hovering over a function and seeing a table of its params like you often see in online documentation. That be great! But at the very least.. recognise some more of the jsdoc tags. Pretty much anything besides @param just gets inlined in the "description", then the line breaks are removed and you end up with this jumbled mess.

fail

Here are a few more things on my wishlist: @see autocompletion with click-to-follow. Also keep jsdocs on imported symbols (right now anything you import via the es2015 syntax will only ever show "import MyClassName" upon hover.) And then, how about optionally allowing for seperate descriptions on a constructor and a class definition
foo.ts

/**
 * some text
 * @class Derp
 */
export class Derp {
    /**
     * builds a new Derp
     * @constructor
     * @param {string} name - the name of the person
     */
    constructor(name: string) {
        this.name = name;
    }
}

bar.ts

import { Derp } from './foo.ts';
     //   ^   hovering shows "some text"

const foobar = new Derp('rozzzly');
                //   ^    hovering shows "builds a new Derp"

if (foobar instanceof Derp) {
                  //   ^   hovering shows "some text"
    // ...
}

@donaldpipowitch @rozzzly thanks a lot for all the suggestions. I will move the issue to the TS team since VSCode leverage the tsserver to provide TS/JS smartness.

Thanks so far. One last request: hovering over an imported module statement could show the description of the corresponding package.json (just like if you hover over dependencies/devDependencies in your own package.json.

Current

// package.json
{
  "dependencies": {
    "express": "^4.13.4"
    // ^ hovering shows:
    //    "express
    //     Fast, unoptionated, minimalist web framework
    //     Latest version: 4.13.4"
  }
}
// foo.ts
import express from 'express';
                  //   ^   hovering shows: "module"

Better

// foo.ts
import express from 'express';
                  //   ^   hovering shows: "Fast, unoptionated, minimalist web framework" (maybe with version...)

There's one more thing that's been a bit lacking with IntelliSense. When a variable is to be of a certain interface and we are defining that object, there are no initial suggestions for the Object's keys until you type the first character -- even if you force-show autocomplete. When I'm defining an object from scratch and I don't remember what other keys it has defined it's been driving me nuts as I have been basically manually iterating through "a", "b", "c", "d"... initial letters to see what other keys I might have forgotten about. This is a problem especially in those times when the type is implicitly inferred and I can't simply CTRL+hover it to see it's declaration. Here's what I mean:

interface Human {
  firstName: string;
  lastName: string;
  age: number;
}

let me: Human = { ... } // <---- when typing inside it would be great to see autocomplete for the properties even BEFORE we type the first letter
// even more annoying when type of 'me' is inferred

Another example would be destructing:

import React, { Component } from 'react';

/**
 * These are the props which can be passed to our component.
 */
export interface NameComponentProps {
  /**
   * This is the name of your user.
   */
  name: string;
}

/**
 * This component says _Hello!_ to your user.
 */
export class NameComponent extends Component<NameComponentProps, {}> {
  render() {
    this.props.name;
                 ^~~~~~| This is the name of your user.
                       | (property) NameComponentProps.name: string
    const { name } = this.props;
              ^~~~~~| const name: string

    return (
      <p className="name-component">
        Hello {name}!
      </p>
    );
  }
}

As you can see the documentation for NameComponentProps.name isn't shown when we use destructing.

@niieani, completion is working for me with just ctrl+space, no need to type additional characters.

animation

@mhegazy Indeed, this seems to be fixed now. Thanks!

To summarize this thread, the request here is for const to inherit the comments from their initialization sources and/or that of their type annotation. if this is not the case, please let me know what i am missing.

there are few open questions, what it mean for expressions in general? e.g. const x = condition ? foo() : bar() is the output the return comments on foo + the return comments on bar? just one of them? or none? what if the const has its own comments? what happens if it has a type annotation, and and an internalizer, which one should be picked?

what if the const has its own comments?

I'd probably introduce the concept of "multiple comments/descriptions". This solves several of the problems above. I wouldn't show all of them at once. Maybe two or so depending on available space and allow pagination in a bigger documentation view to see all of them if wanted.

looking at this again, I do think we really want to build another system to flow comments. the thing that flows through the system are types. if the function provides a special return type, e.g. a set of strings, or a set of numbers, i would recommend using a typedef to define the type and use that instead.

So this isn't wanted or is tracked elsewhere?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

disshishkov picture disshishkov  ·  224Comments

Gaelan picture Gaelan  ·  231Comments

rwyborn picture rwyborn  ·  210Comments

tenry92 picture tenry92  ·  146Comments

sandersn picture sandersn  ·  265Comments