最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to document return value of function that calls another function - Stack Overflow

programmeradmin7浏览0评论

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 that addTen 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 that addTen 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 to addTen, so any change to addTen will indeed affect outerFunction, 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 for outerFunction to reference addTen. – Matt Lishman Commented May 10, 2016 at 10:14
  • Only if you want outerFunction's public contract to be tied to addTen, rather than just its implementation. – T.J. Crowder Commented May 10, 2016 at 10:15
 |  Show 3 more ments

2 Answers 2

Reset to default 5

The 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.

发布评论

评论列表(0)

  1. 暂无评论