Как написать JSDoc для объекта с разными типами ключей?

#javascript #jsdoc #jsdoc3

#javascript #jsdoc #jsdoc3

Вопрос:

API JSDoc говорит, что вы можете документировать объекты следующим образом:

 {Object.<string, number>}
 

и множественный тип документа:

 {(number|boolean)}
 

Но если я попытаюсь указать объект, который может иметь строки ИЛИ числа в качестве ключа, это не сработает. VSCode / JSDoc просто сообщает тип как «любой».

VSCode не понимает:

 /**
 * Object with string or number for keys
 * @param {Object.<(string|number), any>} Container
 */
 

Я также пробовал это в @typedef , или определение ключа в его собственном @typedef безрезультатно.

Потому что я использую amp; для получения intersection типов (например {Object.<string, any> amp; {'foo': number}} , я не хочу использовать логическое значение или говорить:

 /**
 * Object with string or number for keys
 * @param {(Object.<string, any>|Object.<number, any>) amp; {'foo': number}} Container
 */
 

Задокументированный тип в конечном итоге выглядит примерно так:

  type Container = ({
    [x: string]: any;
  } amp; {
    'foo': number;
  }) | ({
    [x: number]: any;
  } amp; {
    'foo': number;
  })
 

Что излишне многословно.

Есть ли способ документировать это с более кратким выводом?

Ответ №1:

В JavaScript ключи объектов всегда являются строками (или, в случае чисел, преобразованы в строки), поэтому вы можете излишне усложнять ситуацию. Смотрите спецификацию ECMAScript для объектов:

Свойства идентифицируются с помощью значений ключей. Значение ключа свойства является либо строковым значением ECMAScript, либо символьным значением. Все строковые и символьные значения, включая пустую строку, действительны как ключи свойств. Имя свойства — это ключ свойства, который является строковым значением.

Целочисленный индекс — это ключ свойства со строковым значением, представляющий собой каноническую числовую строку

Тем не менее, это кажется самым простым решением:

 // Combined
/**
 * @param {Object.<string, any> amp; {foo:  number}} Container
 */

// Split/reusable
/**
 * @typedef {Object.<string, any>} GenericObject
 * @param {GenericObject amp; {foo: number}} Container
 */
 

Оба вышеперечисленных результата приводят к этому типу / документация:

 Container: {
    [x: string]: any;
} amp; {
    foo: number;
}
 

Объявление Object.<string, any> кажется мне немного избыточным, поскольку ключи объекта по своей сути string являются s, а значения по своей сути any , поэтому объявление его таким образом не представляет большой ценности для разработчика.