Skip to content

JSDoc support for array destructuring #1970

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

Open
toxxmeister opened this issue Aug 22, 2016 · 17 comments
Open

JSDoc support for array destructuring #1970

toxxmeister opened this issue Aug 22, 2016 · 17 comments

Comments

@toxxmeister
Copy link

toxxmeister commented Aug 22, 2016

Currently there is no simple way to annotate destructured array parameters.

I propose a syntax similar to the current destructured objects syntax:

/**
 * @param {[x: number, y: number]} randomName
 * @return number
 */
function add([x, y]) {
    return x + y;
}

Due to the nature of destructured arrays, this issue is closely related to #379.

@brad4d
Copy link
Contributor

brad4d commented Oct 6, 2016

Duplicate of #1781

@lll000111
Copy link

It's not really a duplicate, issue #1781 presumes an object.

I'm only commenting because I'm right now trying to find a syntax that works, and ideally one that WebStorm accepts too... I used a JSDoc syntax that ignored that destructuring even takes place which kept the IDE from complaining, but now that I create API docs in HTML I have to find something else - the parameters don't even show up in the output with this workaround...

@shicks
Copy link
Member

shicks commented May 5, 2017

I think what we need is tuple types, which is on our short list for once the NTI migration is complete.

@aaronbeall
Copy link

aaronbeall commented Nov 7, 2017

Additionally, destructuring rest assignment is impossible to represent:

function multiplySum([factor, ...numbersToSum]) {
    const sum = numbersToSum.reduce((a, b) => a + b, 0);
    return sum * factor;
}

And would require a tuple type that can represent "rest" like types:

/**
 * @param {[factor: number, ...numbersToSum: number[]]} args
 */

@narekhovhannisyan
Copy link

narekhovhannisyan commented Jan 17, 2020

Try like this, it's worked for me in VSCode.

/**
 * @param {[x, y]: [Number, Number]} randomName
 * @returns {Number}
 */
function add([x, y]) {
    return x + y;
}

@lll000111
Copy link

@narekhovhannisyan Just an aside, there are two different issues:

  1. JSDoc the format
  2. jsdoc3 the tool to create documentation from JSDoc comments

It's no use for some IDEs to interpret the format, at least I want the documentation producing capability of the tool right here in this repo.

@franktopel
Copy link

There have been no updates on this despite being an open issue for almost 4 years. It has not even been assigned. Is there any hope this might get implemented any time this year?

@brad4d
Copy link
Contributor

brad4d commented Feb 13, 2020

Sadly, I don't think adding this feature is on our 2020 roadmap.

@ctjlewis
Copy link
Contributor

ctjlewis commented Oct 6, 2020

This would be great, but is not exactly critical.

@robfig
Copy link
Contributor

robfig commented Oct 7, 2020

The need to annotate tuples comes up constantly when using React hooks (React.useState). This capability would be extremely useful.

ref: https://groups.google.com/g/closure-compiler-discuss/c/MsoqyuVZL1M/m/lOhWU6R8CAAJ

@ctjlewis
Copy link
Contributor

ctjlewis commented Oct 7, 2020

@robfig Agreed. I applaud you for wanting to compile your React project as well, since they are notoriously bloated with dead code.

The truth is that the Closure Compiler is an internal Google tool, and that the people on this team do a great job of keeping it relatively up-to-date and feature-rich for open source use cases, but you're right that this is definitely a good request.

This is on my wish list along with class fields. Truthfully, React's useState pattern is not very intuitive nor very common, so it was always going to be a poor candidate for Closure Compiler accommodation. It can understand Array<type>, but not different types at different indices.

In the meantime, you can use:

const React = {
  /**
   * @param {number} num
   * @return {Array}
   */
  useState: (num) => [ num, (newNum) => console.log(newNum) ],
};

/** @type {Array} */
const stateTuple = React.useState(Math.random());

/** @type {number} */
const num = stateTuple[0];

/** @type {function(number):number} */
const updateNum = stateTuple[1];

And everything will be typed as expected. I know it's sad to not utilize array destructuring natively, but I would be shocked if this has a meaningful impact on the output size or performance. To test the typing and get output, let's log our variables at the end:

...
console.log({
  /** @type {number} */
  num,
  /** @type {function(number):number} */
  updateNum,
});

Produces:

var a=function(b){return[b,function(c){return console.log(c)}]}(Math.random());console.log({a:a[0],b:a[1]});

Behaves as expected:

VM58:1 {a: 0.6578095262052157, b: ƒ}

Test the typing by breaking a type:

...
// oops!
/** @type {function(string):number} */
  updateNum,
...

Compiler throws:

WARNING - [JSC_TYPE_MISMATCH] assignment to property updateNum of {
  num: number,
  updateNum: function(string): number
}
found   : function(number): number
required: function(string): number
  24|   updateNum,
        ^^^^^^^^^

0 error(s), 1 warning(s), 96.4% typed

These compilations were run with two options:

  1. Maximum compression and DCE with -O ADVANCED.
  2. Use typing with --use_types_for_optimization.

I recommend using the Compiler locally with npm i -g google-closure-compiler, and then the command is simply:

google-closure-compiler -O ADVANCED --use_types_for_optimization myfile.js

@robfig
Copy link
Contributor

robfig commented Oct 10, 2020

Thanks for the guidance.

Since calling React.useState is a common thing to do, I was hoping to make it possible to do so with less ceremony. Going through a wrapper seems like it might be able to streamline things while maintaining type checks:

/**
* @template T
* @param {!T} value
* @return {{val: !T, set: function(!T)}}
*/
WrapReact.useState = function(value) {
  const state = React.useState(value)
  const val = /** !T */ (state[0]);
  const set = /** function(!T) */ (state[1]);
  return {val: val, set: set}
}

const num = WrapReact.useState(Math.random());

console.log(num.val);
num.set(Math.random());

It seems to work in the online playground

@heydarm
Copy link

heydarm commented Apr 26, 2021

These work in VS Code:

/**
 * @param {[x: number, y: number]} param
 * @returns {[x: number, y: number]}
 */
function doNothing([x, y]) {
    return [x, y];
}

and

/**
 * @param {[number, number]} param
 * @returns {[number, number]}
 */
function doNothing([x, y]) {
    return [x, y];
}

@ctjlewis
Copy link
Contributor

Yes, but the compiler can't handle them as far as I'm aware.

@joneldiablo
Copy link

Additionally, destructuring rest assignment is impossible to represent:

function multiplySum([factor, ...numbersToSum]) {
    const sum = numbersToSum.reduce((a, b) => a + b, 0);
    return sum * factor;
}

And would require a tuple type that can represent "rest" like types:

/**
 * @param {[factor: number, ...numbersToSum: number[]]} args
 */

soooo, the destructuring rest assignment has any way to be documented?

@ctjlewis
Copy link
Contributor

@joneldiablo, I would not count on it. I have pitched Google about allocating more resources to the compiler, but it was shot down.

I would not count on new features being added anytime soon, and this tool is maintained largely for the sake of internal Google projects.

@joneldiablo
Copy link

@joneldiablo, I would not count on it. I have pitched Google about allocating more resources to the compiler, but it was shot down.

I would not count on new features being added anytime soon, and this tool is maintained largely for the sake of internal Google projects.

oh, sad. =(
thankyou

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests