-
-
Save ritch/9606670 to your computer and use it in GitHub Desktop.
/** | |
* 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 | |
*/ |
@raymondfeng - what would that look like for a dynamic key? Eg. in a Map
.
I would make people
an Array, which is easier to describe and then I'd describe the return value as a dictionary mapping names to zipcodes. I think the underlying problem is JavaScript's conflation of Object and a general purpose dictionary type.
/**
* @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
*/
I would use the syntax used by Google Closure Compiler (link)
{Object.<string, number>}
An object in which the keys are strings and the values are numbers.
/**
* @param {Object.<string, Person>} people An index of people keyed by a person's name
* @returns {Object.<string, ZipCode} map An index of zipcodes keyed by a person's name
*/
The description does not say the string key is a person name. A OOP purist would say you should wrap the primitive type in your custom type, but that seems like an overkill in a dynamic typed javascript.
/**
* @param {Object.<Person.Name, Person>} people An index of people keyed by a person's name
* @returns {Object.<Person.Name, ZipCode} map An index of zipcodes keyed by a person's name
*/
On the other hand, since we are not using the Closure compiler, I suppose it's ok to use types that don't exist, like Person.Name
.
@bajtos - where would you define Person
? Maybe that is what is missing. The ability to document a type that doesn't exist in the code...?
...then why even have a dynamic language... some might say.
@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.
I am working with following:
/**
* @typedef {{
* firstName: string,
* age: number
* }} Person
*
* @param {{
* [key: keyof Person]: Person
* }} p
*/
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
*/
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
*/
What about http://usejsdoc.org/tags-property.html?