microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
100.51k stars 12.43k forks source link

Feature Request: Display JSDoc Array of Objects as Array #58901

Open agbrettpittman opened 4 months ago

agbrettpittman commented 4 months ago

Hey guys,

I tried searching for a similar issue, but couldn't find one. If there is another, I'm happy to close this one. Essentially, when specifying that a particular entity is an array of objects with a definite shape, I would like it if those were displayed as an actual array. Given the following Javascript:

/**
 * @param {Object} params
 * @param {Object[]} params.items - Array of items
 * @param {string} params.items[].name - Name of the item
 * @param {string} params.items[].value - Value of the item
*/
function myFunc({ items = []}){
    items.map(item => {
        console.log(item.name, item.value)
    })
}

Currently, on hover, VSCode displays the type hinting as:

function myFunc({ items }: {
    items: {
        name: string;
        value: string;
    };
}): void

However, this makes it appear that items is an object. That is incorrect because items is instead an array of objects, and is specified as such in the JSDoc. I would expect something akin to when you specify the properties inline:

JS:

/**
 * @param {Object} params
 * @param {{name: string, data: string}[]} params.items - Array of items
*/
function myFunc({ items = []}){
    items.map(item => {
        console.log(item.name, item.value)
    })
}

Hover:

function myFunc({ items }: {
    items: {
        name: string;
        data: string;
    }[];
}): void

The problem with using the inline format is the lack of an explanation of individual properties, and some object shapes can get very long, and even be nested. Additionally, the above solution waits until the end of the object definition to denote that the property should be an array. It seems that it would be more user-friendly if it was denoted as an array at the beginning, like this:

function myFunc({ items }: {
    items: [{
        name: string;
        data: string;
    }];
}): void

Thanks for your time and the great product!!

IllusionMH commented 4 months ago

In your last example you have tuple with one object in it [{ name: string; data: string; }];, not an array of objects so it shouldn't be expected result.

agbrettpittman commented 4 months ago

Hey @IllusionMH to the best of my knowledge tuples still do not exist in Javascript...they are currently a TC39 proposal, (you can see this here) but have not been accepted into the spec yet. Additionally, the part you quoted is missing the necessary "#" symbol for tuples in said proposal. Therefore, I'm not sure how exactly that could be the syntax for tuples. Further, my last example was a suggestion of a potential hover hint format for VSCode, not true Javascript syntax.

If you can link to any docs saying that that is a hover hint format that is already in use, whether for tuples or not, I'll happily read it, and we can disregard that particular hint format suggestion. Even in that situation, the overall thrust of the feature request remains: a way for VS Code to correctly display that a given parameter for a function should be an array of objects where those objects have a defined / expected shape.

Thanks for your time!!

IllusionMH commented 4 months ago

Hi! I'm not talking about JS Tuples (& Records), but about TS Tuples. TS powers JS features, including hovers, and hovers are TS types. See note for arrays and linked docs on tupels.

My comment only about later proposal to nothe that T[] and [T] are different things and not interchangeable. Closest thing would be display it as Array<T> instead of T[] (see https://github.com/microsoft/TypeScript/issues/44715)


As for rest of the post - it looks like bug to me. Or at least syntax that is not properly supported by TS.

Workaround would be using inline object, as you shown or move item object to @typedef

agbrettpittman commented 4 months ago

Ah, I see what you're saying. Thanks for the helpful docs! I actually tried the typedef yesterday and did not include it because the current way typedefs are represented makes sense to me. They don't help in this specific situation, but they make sense. When I use a typedef, I simply get the name of the type def next to the "[]". Here is an example:

JS

**
 * @typedef {Object} item
 * @property {string} name - Name of the item
 * @property {string} value - Value of the item
 * 
 * @param {Object} params
 * @param {item[]} params.items - Array of items
*/
function myFunc({ items = []}){
    items.map(item => {
        console.log(item.name, item.value)
    })
}

Hover

function myFunc({ items }: {
    items: item[];
}): void

I cannot find a way to view the required properties of "item", so it doesn't solve my use case. However, I understand that in a full TS project, those types can be found / hovered elsewhere. So, I'm not asking that that be changed (although I'm ambivalent on that front), only that an array of objects be in some way denoted as an array. If the most logical way for that to happen is to have the "[]" after the object definition, that would definitely fulfill this feature request.

I appreciate your regular responses!