Я использую JSDoc уже некоторое время, и в связи с недавней шумихой из-за миграции Svelte, сегодня я пришел поделиться советами и тем, как их использовать.
Это самые основы того, что вам понадобится.
Машинопись
Синтаксис для некоторых вещей отличается, но для большинства вещей просто думайте об этом как о Typescript, и все будет в порядке.
файлы .d.ts
Я обычно использую их для вспомогательных и служебных типов (их проще создать, особенно с дженериками, и потом их можно просто использовать)
Настраивать
Добавьте // @ts-check
в начало каждого файла, который вам нужен, или добавьте jsconfig,json
в корень вашего проекта с проверочными JS-файлами. (Не забудьте включить js checking
в вашей IDE).
JSDoc
@тип
Как и в случае с TS, есть разница между:
/** @type {Foo} */ const foo = {} const foo: Foo = {} // and const foo = /** @type {Foo} */ ({}) const foo = {} as Foo // also includes const foo = /** @satisfies {Foo} */ ({})
В зависимости от того, как вы хотите, чтобы TS обрабатывал тип, автозаполнение и ошибки, которые он вам показывает.
Для @type
я обычно делаю это встроенным, потому что я обычно использую его для приведения чего-то к нужному мне типу:
// React common example const [state, setState] = useState(/** @type {{ foo: Bar, bar: Baz }} */ ({})); // ^? { foo: Bar, bar: Baz } // And then sometimes you need some casting Object.keys(state).map(k => k) // ^? string /** @type {(keyof state)[]} */ (Object.keys(state)).map(k => k) // ^? "foo"|"bar"
И, как вы могли видеть, при приведении чего-то к типу вы заключаете его в круглые скобки /** @type {Foo} */ (toBeCast), и, конечно, если вам нужно, вы можете /** @type {Foo} */(/** @type {unknown} */ (toBeCast)) и да, для этого вам нужно поместить его внутрь двух.
@typedef
Вы, вероятно, будете использовать много, обычно для более сложных типов.
Для этого я объявляю его как блок и обычно первым способом без каких-либо комментариев.
Но иногда вам нужна вторая версия, потому что куда бы ни пошли эти типы, там же и комментарии.
/** * @template {string} [T='bar'] * @typedef {{ * bar: T, // you can't see this comment * baz?: string, * }} Foo visible comments here */ /** * @template {string} [T='bar'] * @typedef {Object} Foo2 * @property {T} bar this comment is visible * @property {string} [baz] this is an optional property */ // both equivalent to: type Foo<T extends string = "bar"> = { bar: T; baz?: string; }
Что касается @template
, самый простой способ объявить дженерик — это @template T
.
Тот, что в примере, является самым сложным, который вам понадобится, с типом, который он расширяет, а затем значением по умолчанию, но вы также можете иметь только одно или другое.