javascriptjsdoc

How to type an object with dynamic keys?


How can I achieve typehinting an object having dynamic keys with JavaScript / JSDocs only? (TypeScript knows index signature, yet this is not for TypeScript.)

I want to use JSDoc to document an argument object for a function to get type inference for my tooling.

(I work with PhpStorm, yet the solution should be agnostic to the IDE).

I thought I could achieve with what I want via:

/**
 * @typedef SomeOther
 * @type {string} a
 * @type {boolean} c
 * @type {number} d
 */

/**
 * @typedef Dynamic
 * @type {{[key: string]: SomeOther}}
 */

/**
 * @param {Dynamic} arg
 */
const foo = (arg) => {
    const example = arg['foo'];
    example.
};

Yet once I open autocomplete in the example, I see no recommendations. The type is not inferred:

Example showing no typehints

I also tried this approach


class ClassAsTypehint {
    /**
     * @this {{[k: string]: SomeOther}}
     * @param {string} key
     */
    getProp(key) {
        return this[key];
    }
}

/**
 * @param {ClassAsTypehint} arg
 */
const foo = (arg) => {
    const example = arg['foo'];
    example.
};

Similar result:

typehint also as class not working

For completeness, I can verify that my basic type inference works:

Type inference works with simple objects


Solution

  • SomeOther is incorrectly defined, try like this (prop is just shorthand for property):

    /**
     * @typedef SomeOther
     * @prop {string} a
     * @prop {boolean} c
     * @prop {number} d
     */
    

    Then inline the type definition of Dynamic like this:

    /**
     * @typedef {{[key: string]: SomeOther}} Dynamic
     */
    

    This inference should then properly work:

     /**
     * @param {Dynamic} arg
     */
    const foo = (arg) => {
      
        const example = arg['foo'];
        example.a
    };