Как правильно получить предполагаемые типы возвращаемых значений в функции-оболочке с помощью jsdoc в vscode?

Вот некоторый код (упрощенный), чтобы лучше понять:

Оболочка для отправки запросов

  • Он выполняет некоторые общие действия при отправке запроса и при его завершении.
  • Возвращает результат запроса (обработчик).
async function request (handler) {
  // common stuff
  try {
    const result = await handler()
    return result || true
  }
  catch (err) {
    doSomethingWithError(err)
    return err
  }
  finally {
  // common stuff
  }
}

/**
 * Imagine a simple service / api client
 */
const someApiClient = {
  /**
   * @returns {Promise<string[]>} 3 first letters
   */
  async getSomeData () {
    return ['a', 'b', 'c']
  }
}

/**
 * Just a function or method using the api client, that has types declared
 */
async function fetchMeSomeDataHandler () {
  return someApiClient.getSomeData()
}

const result = await request(() => fetchMeSomeDataHandler())

Ожидал

Здесь я ожидаю, что vscode / jsdoc сделает вывод, что тип результата — строка [] и даже даст мне описание от клиента API (3 первые буквы).

Но это не так, он даст тип any в конце.

Что мы получаем в vscode

Если мы проследим за типами, подобранными vscode, мы увидим, что он постепенно теряет типы, пока ничего не останется.

  1. Полное описание типа подобрано для клиента API.

Полное описание типа в API-клиенте

  1. Тип известен в определении обработчика, но мы потеряли описание клиентского значения (3 первые буквы).

Тип известен в определении обработчика, но мы потеряли описание клиентского значения

  1. Мы полностью потеряли информацию о типе для окончательного результата

Мы полностью потеряли информацию о типе


person Kev    schedule 27.08.2020    source источник


Ответы (1)


VS Code пытается вывести типы параметров функции на основе их использования. Простой пример этого:

function foo(a) {
    return a.b;
}

foo({ b: 3 })

В результате foo имеет подпись function foo(a: any): any. Ваш код является более сложным примером этого ограничения.

Исправление состоит в том, чтобы явно аннотировать тип параметра на request:

/**
 * @template T
 * @param {() => Promise<T>} handler 
 * @return {Promise<T>}
 */
async function request(handler) {
   ...
}

В этом конкретном случае нам также нужен явный @returns, так как блок catch не возвращает значение типа T (он возвращает any, так как ошибка нетипизирована).

Вы можете опустить @returns, если request было написано:

/**
 * @template T
 * @param {() => Promise<T>} handler 
 */
async function request(handler) {
    // common stuff
    const result = await handler()
    return result
}

Поскольку VS Code может определять возвращаемые типы функций (но имейте в виду, что явные типы полезны во многих случаях, особенно для функций, которые могут возвращать несколько разных типов).

После добавления явных типизаций result должен иметь правильный тип:

введите здесь описание изображения

person Matt Bierner    schedule 28.08.2020
comment
Выглядит неплохо! Но ключевым моментом здесь является аннотация @template T. Я не вижу этого в документации jsdoc. Кажется, это тег, связанный с typescript? Я могу найти его здесь: typescriptlang.org/docs/handbook/jsdoc- поддерживаемые типы.html - person Kev; 29.08.2020