如何记录由扩展对象与其他属性组合而成的函数的返回?

Posted

技术标签:

【中文标题】如何记录由扩展对象与其他属性组合而成的函数的返回?【英文标题】:How to document the return of a function, that is made from combining a spread objects with other properties? 【发布时间】:2021-12-26 17:03:54 【问题描述】:

我有代码可以传播返回的对象,并添加一个新属性

看起来像这样:

/**
 * it does the things
 * @param Object input object containing id and key
 * @param Object.string id unique id to associate with return value
 * @param Object.string key unique key used to get things
 * @returns Object.<???, id:string> the returned things and id.
 */
const doTheThings = (id, key) =>
  thingDoer(key).then(things => 
    ...things, // how do I document the properties of this
    id         // combining with this?
  )

我目前在@returns 部分中有??? 等于things: *。但这看起来好像在返回中会有一个名为“things”的键,而实际上没有。

我如何记录things 是什么?如果 thingDoer 有自己的 JSDoc 我可以依靠,它会改变吗?最好不涉及打字稿。

【问题讨论】:

这里听起来很一般。你拿T 并返回它丰富。它总是添加相同的属性(things)还是可以不同? @VLAZ 除了 javascript 没有泛型。当您说“它总是添加...”时,您的意思是函数thingDoer 是否总是返回相同的things?是的,它始终是相同的形状,但值可能会改变。 "除了 JavaScript 没有泛型" 但 JSDoc 有 ;) 即使它们没有很好的文档记录。 “是的,它始终是相同的形状,但值可能会改变。”那么也许泛型是矫枉过正。如果总是一样,也许你只需要@typedef 【参考方案1】:

它使用扩展语法的事实是无关紧要的。您记录功能做什么不一定如何。因此,它需要 一些 对象并(可能)使用更多属性来丰富它,以保持 id 就位。

/**
 * @typedef Thingamajig 
 * @type object
 * @property number foo - some number here
 * @property string bar - a string used for something
 */

/**
 * Transforms things.
 * @param string key - what to transform
 * @return Promise<Thingamajig> - transforms into this
 */
function thingDoer(key)  /* .... */ 

/**
 * it does the things
 * @param Object input - object containing id and key
 * @param string input.id - unique id to associate with return value
 * @param string input.key - unique key used to get things
 * @returns Promise<Thingamajig & id:string> the returned things and id.
 */
const doTheThings = (id, key) =>
  thingDoer(key).then(things => 
    ...things,
    id
  )

See on the TypeScript Playground - 文件类型已设置为 JavaScript(可在 TS 选项 下找到),因此这纯粹是演示如何解释 JSDoc 的一种方式。将鼠标悬停在函数和参数上以查看它们的类型。

这里的关键是使用@typedef 声明thingDoer 返回和doTheThings 也使用的相同对象结构。这样,如果它改变了,你只改变一个地方。

doTheThings 函数然后返回 Thingamajig &amp; id:string,这是一个 Thingamajig,并添加了一个字符串 id 属性。另一种方法是创建另一个 typedef,如 ThingamajigWithId 并在那里记录属性。取决于使用 JSDoc 的工具。

/**
 * @typedef ThingamajigWithId
 * @type object
 * @property number foo - some number here
 * @property string bar - a string used for something
 * @property string id - unique identifier.
 */

您可以使用an intersection (the &amp;) 做的一件有趣的事情是分别使用 ID 声明类型,然后将两者相交。这样您就可以记录它:

/**
 * @typedef Thingamajig 
 * @type object
 * @property number foo - some number here
 * @property string bar - a string used for something
 */

/**
 * @typedef WithId
 * @type object
 * @property string id - unique identifier
 */

/** ...
 * @returns Promise<Thingamajig & WithId> the returned things and id.
 */

See on the TypeScript Playground

请注意,类型交集不是 JSDoc 本身的一部分。它们是 TypeScript 的一项功能。根据使用 JSDoc 的工具,它可能会或可能不会起作用。例如,Visual Studio Code 可能不会抱怨,但是,如果您有一个从注释构造文档的工具,它可能无法将 &amp; 识别为有效。


另请注意,在 JSDoc 本身中添加这种类型的对象扩展是一个长期存在的功能:

Issue on GitHub 自 2016 年 4 月起 关于引发它的 Stack Overflow 的问题:How to extend a typedef parameter in JSDOC?

目前似乎没有一种方法可以扩展满足所有 JSDoc 使用者的 typedef。唯一似乎保证可以工作的事情是手动创建一个 typedef 手动重复所有属性(我在上面展示过):

/**
 * @typedef ThingamajigWithId
 * @type object
 * @property number foo - some number here
 * @property string bar - a string used for something
 * @property string id - unique identifier.
 */

然而,Thingamajig 的基本 typedef 并没有改变,这使得维护起来很烦人。以下是可能支持的不同内容的简要概述

使用交集适用于任何基于 TypeScript 的解释。 还有一个插件可以扩展 JSDoc 以识别&amp;。 一些工具似乎支持使用 | 代替,并且会显示 A | B 具有来自 AB 的两个属性,即使它应该是一个替代。 一些工具可以识别
/** 
 * @typedef A, B Combined 
 */
一些工具可以识别
/** 
 * @typedef Combined 
 * @type A, B
 */

我找不到一种似乎在任何地方都能始终如一地工作的技术。

【讨论】:

以上是关于如何记录由扩展对象与其他属性组合而成的函数的返回?的主要内容,如果未能解决你的问题,请参考以下文章

结构体,枚举类型

编写一个函数isMerge,判断一个字符串str是否可以由其他两个字符串part1和part2“组合”而成

超强大几十款功能组合而成的一款工具箱微信小程序源码下载支持N个流量主

元素操作等等

面向对象

建造者模式