154

I am having a function that accepts one string parameter. This parameter can have only one of a few defined possible values. What is the best way to document the same? Should shapeType be defined as enum or TypeDef or something else?

Shape.prototype.create = function (shapeType) {
    // shapeType can be "rect", "circle" or "ellipse"...
    this.type = shapeType;
};

Shape.prototype.getType = function (shapeType) {
    // shapeType can be "rect", "circle" or "ellipse"...
    return this.type;
};

The second part of the problem is that the possible values of shapeType is not known in the file that defines shapeType as whatever you suggest. There are multiple files contributed by several developers who might add to the possible values of shapeType.

PS: Am using jsdoc3

Shamasis Bhattacharya
  • 3,392
  • 3
  • 20
  • 24
  • The multiple files problem makes this difficult. I usually see an `enum` for the definition and a union for the function parameter: `ShapeType|string`. However enums don't support adding subtypes after declaration in Closure-compiler. – Chad Killingsworth Sep 30 '13 at 17:56
  • @ChadKillingsworth I see what you mean. I am stuck at a point where I want to define a set of properties (lets say an object that goes as construction parameter of a class). It is well and good had all properties of the construction was defined at one location. Unfortunately, my code has a number of modules contributing to that construction properties. Doing something like a mixin or subclassing the propertied would be going overboard! As such, if I can simply inject to a property list definition it would be great. – Shamasis Bhattacharya Oct 01 '13 at 09:58
  • Another similar issue that I am facing, but with distributed property listing is http://stackoverflow.com/questions/19113571/adding-sub-properties-to-an-existing-property-list-in-jsdoc – Shamasis Bhattacharya Oct 01 '13 at 10:15
  • All solutions below force us to create an Enum. There is an active feature request at GitHub to make this process much easier: https://github.com/jsdoc3/jsdoc/issues/629. So anybody who likes it should probably bump it. – Felix K. Jan 07 '16 at 14:15

5 Answers5

198

As of late 2014 in jsdoc3 you have the possibility to write:

/**
 * @param {('rect'|'circle'|'ellipse')} shapeType - The allowed type of the shape
 */
Shape.prototype.getType = function (shapeType) {
  return this.type;
};

Of course this will not be as reusable as a dedicated enum but in many cases a dummy enum is an overkill if it is only used by one function.

See also: https://github.com/jsdoc3/jsdoc/issues/629#issue-31314808

Felix K.
  • 14,171
  • 9
  • 58
  • 72
71

What about:

/**
 * @typedef {"keyvalue" | "bar" | "timeseries" | "pie" | "table"} MetricFormat
 */

/**
 * @param format {MetricFormat}
 */
export function fetchMetric(format) {
    return fetch(`/matric}`, format);
}

enter image description here

puemos
  • 1,109
  • 9
  • 12
  • Hey, is it possible to list the values from existing array? let say, I have array of string values, and I need to limit the input to the text that includes in this array – Kostanos Mar 09 '23 at 16:11
35

How about declaring a dummy enum:

/**
 * Enum string values.
 * @enum {string}
 */
Enumeration = {
    ONE: "The number one",
    TWO: "A second number"
};

/**
 * Sample.
 * @param {Enumeration} a one of the enumeration values.
 */
Bar.prototype.sample = function(a) {};


b = new Bar();

bar.sample(Enumeration.ONE)

You need to at least declare the enum to JSDOC, for this, though. But the code is clean and you get auto-completion in WebStorm.

The multiple files problem though cannot be solved this way.

Sebastian
  • 7,729
  • 2
  • 37
  • 69
  • 1
    Yes. The enumeration approach is the only usable way I see. Anyways, I accept this as the only usable answer - since the multi-file problem is another story altogether! – Shamasis Bhattacharya Oct 13 '13 at 17:39
  • The problem with this approach is that it does not allow to document the individual values. I have an issue with JSDoc. https://github.com/jsdoc3/jsdoc/issues/1065 – Gajus Sep 17 '15 at 13:46
  • I don't see how this can be ok. Parameter "a" is expected to be an object with two properties, but you provide a string to the function. – Lideln Kyoku Aug 13 '23 at 10:00
  • @LidelnKyoku - It works, because the type is *declared* to be an enum and then gets special treatment. `Enumeration` is not an object *type* but an enum type with string values. [it does work](https://www.typescriptlang.org/play?module=1&resolveJsonModule=true&filetype=js#code/PQKhCgAIUhRA7ArgW0gZwC4CcCW8DmkAbgIYA2iApmgHRQwAClSqA3prgQL73DgDGAe3iY4LSlhIYcwyAF5IrKJBUB5AHKwAXJABEAFQAWlSCwBGEyMMq6ANMpX6A6qp26AgukpD4AE1MoFli64FwA3ODgoBDQkADKJMgADmSUdLEMSSSSbAgoElIy8FyQJFbwJoIAZpAYxpDM+ZLSsqQU1OkgfFWI8Pwt8LXUGAAUJACUipAOpRHAwCoAegD8oRGRGMMjecgFAzQasONAA) – Sebastian Aug 25 '23 at 08:06
12

I don't think there's a formal way of writing allowed values in JSDoc.

You certainly can write something like @param {String('up'|'down'|'left'|'right')} like user b12toaster mentioned.

enter image description here

But, by taking reference from APIDocjs, here's what I use for writing constrained values, aka allowedValues.

/**
 * Set the arrow position of the tooltip
 * @param {String='up','down','left','right'} position pointer position
 */
setPosition(position='left'){
  // YOUR OWN CODE
}

Oh yeah, I'm using ES6.

Community
  • 1
  • 1
Alan Dong
  • 3,981
  • 38
  • 35
  • 3
    `@param` does not allow this type of syntax. The most standard way would be `@param {"up"|"down"|"left"|"right"} [position=left] - pointer position`. – RiZKiT Dec 17 '21 at 09:33
1

This is how the Closure Compiler supports it: you can use "@enum" to define a restricted type. You don't actually have to define the values in enum definition. For instance, I might define an "integer" type like:

/** @enum {number} */
var Int = {};

/** @return {Int} */
function toInt(val) {
  return /** @type {Int} */ (val|0);
}

Int is generally assignable to "number" (it is a number) but "number" is not assignable to "Int" without some coercion (a cast).

John
  • 5,443
  • 15
  • 21
  • But that doesn't restrict the possible values of `Int`. That's the part I'm not sure is possible. – Chad Killingsworth Oct 01 '13 at 13:10
  • It does as much as any other type annotation or enum in JS. The restriction comes from how you write the code: every "cast" is a red flag. If you limit the casts to value factories then you get what you want: you can't assign 'number' to 'Int' without a warning. – John Oct 01 '13 at 15:23
  • It still doesn't restrict the values of {Int}. :-( – Shamasis Bhattacharya Oct 08 '13 at 19:13
  • Sure it does, you restrict the value of Int by limiting how it is created and the restriction is done when the value is created. A raw number can not be assigned which is all you need. – John Oct 15 '13 at 16:01