Skip to content

Instantly share code, notes, and snippets.

@ritch
Last active September 6, 2023 04:27
Show Gist options
  • Save ritch/9606670 to your computer and use it in GitHub Desktop.
Save ritch/9606670 to your computer and use it in GitHub Desktop.
What is the best way to document complex / dynamic objects as arguments to a function?
/**
* Below are several examples of methods that are difficult to clearly annotate with JSDoc annotations.
*/
/**
* @param {Object} people An index of people keyed by a person's name
* @returns {Object} map An index of zipcodes keyed by a person's name
*/
function find(people) {
return Object.keys(people).reduce({}, function(prev, cur) {
prev[cur] = zipFor(cur);
return prev;
});
}
/**
* @param {Object} options The options to set
*/
function configure(options) {
this.options = options;
}
/**
* @param {Object} options The options to set
*/
function configure(options) {
this.options = options;
}
/**
* @param {Object} options The options to set
* @param {Object} options.server The server options
* @param {String} options.server.host The server host
* @param {String|Number} options.server.port The server port
* @param {Array} options.remoteHosts An array of server options
*/
function betterConfigure(options) {
this.options = options;
}
/**
* The issue:
*
* - the documentation above is not clear and sometimes incomplete
* - an example would help, but would not be explicit
* - it is difficult to describe objects within arrays
*/
@bajtos
Copy link

bajtos commented Mar 18, 2014

@ritch It was not clear to me that the structure is a nested key-value structure with not classes. Your original plain english comment did not provide any details on what "person" is. Perhaps we can assume the reader already knows that.


The Closure type system has a notion of records:

{{myNum: number, myObject}}
An anonymous type with both a property named myNum that has a value of type number and a property named myObject that has a value of any type.

Together with @typedef:

/**
 * @typedef {name:string, age:number} Person
 * @param {Object.<Person.Name, Person>} people
 * @returns {Object.<Person.Name, ZipCode} map
 */

To be honest, this approach makes sense only if there is a tool that can parse type definitions and display them in an easily consumable format. Otherwise it's probably better to describe the structure using plain english.

@reduardo7
Copy link

I am working with following:

/**
 * @typedef {{
 *    firstName: string,
 *    age: number
 *  }} Person
 *
 * @param {{
 *    [key: keyof Person]: Person
 *  }} p
 */

@Abrifq
Copy link

Abrifq commented Jul 3, 2020

I am working with following:

/**
 * @typedef {{
 *    firstName: string,
 *    age: number
 *  }} Person
 *
 * @param {{
 *    [key: keyof Person]: Person
 *  }} p
 */

Oh, thank you! I was trying to document a hybrid object (which has both static and dynamic properties) for my project and after observing <key,value> example and your example, I finally managed to achieve something like this:

/**@typedef {{
* [jobID:number]: Job,
* jobCount: number
* }} JobDatabase
*/

@xgqfrms
Copy link

xgqfrms commented Sep 6, 2023

Why is it not working for me?

An index signature parameter type cannot be a literal type or generic type. Consider using a mapped object type instead.ts(1337)

/**
 * @typedef {{
*    firstName: string,
*    age: number
*  }} PersonX
*
*/

/**
* @param {{
*    [key: keyof PersonX]: PersonX
*  }} px
*/

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