Given the following example:
/**
* An outer function
* @param {number} age - The age to pass to outerFunction
* @returns {#What goes here?#}
*/
function outerFunction(age){
return addTen(age)
}
/**
* Adds 10 to the age
* @param {number} age - The age to add 10 to
* @returns {number} - The age + 10
*/
function addTen(age){
return 10 + age
}
the outerFunction
returns another function's result.
I thought of several ways to document this:
@returns {number}
- We know thataddTen
returns a number, but what if this changes? We will have to update both (or each time it is returned, which could be a lot), which isn't maintainable.@returns {function}
- I am not sure if this is available in JsDoc. I couldn't find it anywhere. This also doesn't feel like it gives much information.@returns {any}
or -@returns {*}
- This isn't particularly helpful to anyone reading the doc.
None of these feel correct to me for the reasons stated.
I guess I want something like
@returns {addTen.return}
So that I am essentially saying "outerFunction
returns whatever type addTen
does".
Note: these are in the same place in this example, but could be contained in multiple files, so using this approach doesn't work, unless it's possible to do this across multiple files.
How do we write JsDoc ments to document that the function returns another function?
Does something similar to my suggestion exist?
Given the following example:
/**
* An outer function
* @param {number} age - The age to pass to outerFunction
* @returns {#What goes here?#}
*/
function outerFunction(age){
return addTen(age)
}
/**
* Adds 10 to the age
* @param {number} age - The age to add 10 to
* @returns {number} - The age + 10
*/
function addTen(age){
return 10 + age
}
the outerFunction
returns another function's result.
I thought of several ways to document this:
@returns {number}
- We know thataddTen
returns a number, but what if this changes? We will have to update both (or each time it is returned, which could be a lot), which isn't maintainable.@returns {function}
- I am not sure if this is available in JsDoc. I couldn't find it anywhere. This also doesn't feel like it gives much information.@returns {any}
or -@returns {*}
- This isn't particularly helpful to anyone reading the doc.
None of these feel correct to me for the reasons stated.
I guess I want something like
@returns {addTen.return}
So that I am essentially saying "outerFunction
returns whatever type addTen
does".
Note: these are in the same place in this example, but could be contained in multiple files, so using this approach doesn't work, unless it's possible to do this across multiple files.
How do we write JsDoc ments to document that the function returns another function?
Does something similar to my suggestion exist?
Share Improve this question edited May 23, 2017 at 12:24 CommunityBot 11 silver badge asked May 10, 2016 at 10:08 Matt LishmanMatt Lishman 1,8172 gold badges23 silver badges34 bronze badges 8-
"the
outerFunction
returns another function" No, it doesn't. It returns the result of calling another function, which is something else entirely. From the remainder of the question I think you know that, so it's not an answer, but... – T.J. Crowder Commented May 10, 2016 at 10:11 - Ah, good point! My question still stands, in a slightly different format though... I will edit it. I would still like to know how to correctly document this. – Matt Lishman Commented May 10, 2016 at 10:12
-
1
"We know that
addTen
returns a number, but what if this changes? We will have to update both (or multiple), which isn't maintainable." Well,outerFunction
is tightly bound toaddTen
, so any change toaddTen
will indeed affectouterFunction
, which has knock-on effects -- to the documentation, but more importantly to its functionality. – T.J. Crowder Commented May 10, 2016 at 10:13 -
So, you're saying that when I change the way that
addTen
works, I also have to change each time anything returns it? I guess I want the documentation forouterFunction
to referenceaddTen
. – Matt Lishman Commented May 10, 2016 at 10:14 -
Only if you want
outerFunction
's public contract to be tied toaddTen
, rather than just its implementation. – T.J. Crowder Commented May 10, 2016 at 10:15
2 Answers
Reset to default 5The caller of outerFunction
will have certain expectations of what that function accepts as arguments and what it will return. The caller of outerFunction
does not care what outerFunction
does, only that its interface works as described. The caller of outerFunction
does not know or care nor should they care that some function called addTen
is involved in anything outerFunction
does. In fact, someday you may rewrite the entire implementation of outerFunction
to not call addTen
anymore, but keep it behaving exactly the same way.
Treat every function individually as a black box. You're describing the interface of outerFunction
, so describe what it does/is supposed to do. Don't describe it in terms of some other function which may or may not be related. If outerFunction
is expected to return a number, describe it as such. If addTen
also happens to return a number, well, what a coincidence.
I understand the impetus to want to implicitly tie the return value of one function to that of another, because that's how it's actually implemented, and you know... DRY and all... But in this case that's counter productive. It doesn't matter that you "repeat" the "same information" about the return type on two different functions; because you're not describing a connected thing. Both functions are independent black boxes with their own specific signature; that their implementation happens to be coupled is irrelevant for that, and may in fact change tomorrow. What is important is that the signature stays as described.
In fact, if addTen
did change its return type (and implicitly so did outerFunction
), that would be a big deal anyway that's not just going to blow over by implicitly updating some documentation. By changing the return type of any function, you're breaking a previously established contract, which will have a cascade of effects to every user of that function. Implicitly and automatically updating the return type of outerFunction
is the least of your worries in such a scenario, as you might have to rewrite large swaths of code to conform to the new contract.
This is an old question, but I just encountered a similar issue recently. I'm leaving my solution for anyone who has this issue to refer to. But please note that all I needed were some type hints in VS Code. If you are using some docgen tools, or you can only use the official jsdoc syntax then this answer is probably not for you.
So in this example, if all you need are some type hints in editors, you don't need to add any return type to the outerFunction
:
/**
* An outer function
* @param {number} age - The age to pass to outerFunction
*/
function outerFunction(age){
return addTen(age)
}
The above code will work automatically (if addTen
is properly typed). But if you really need to reference the return type of addTen
, for example:
// The param `addedAge` is definitely something returned by `addTen`
function outerFunction(addedAge) {
return addedAge + addTen(10) // bees `any`
}
In this example if addedAge
is a number, outerFunction
returns a number; if addedAge
is a string, then it returns a string as well. In this case you can:
/**
* @param {ReturnType<addTen>} addedAge
* @returns {ReturnType<addTen>}
*/
function outerFunction(addedAge) {
return addedAge + addTen(10)
}
Again, this is not the official jsdoc syntax, but for editors like VS Code, the typing system is built on top of TypeScript so you can use TypeScript features directly.
Besides, you can even import a type (or function) in jsdoc:
/**
* @param {ReturnType<import('../fn').addTen>} addedAge
*/
function outerFunction(addedAge) {
return addedAge + addTen(10)
}
For anyone who wants some types but can't migrate to TypeScript yet, I hope this will help.