Как создать функцию, которая динамически возвращает тип Promise

Я нахожусь в сценарии, когда я знаю, какие данные будут возвращены при выборке в API,

У меня есть следующая функция

const fetchingData = async (url: string, options?: Object): Promise<any> => {
  const res = await fetch(url, options);
  const data = await res.json();
  return data;
};

Эта функция возвращает обещание типа any, но как я могу создать обещание, которое может возвращать независимо от того, какой тип я передаю здесь Promise, чтобы получить типизированный ответ?

Я имел в виду что-то вроде этого примера

interface One{
...
}
interface Two{
...
}

const fetchingData = async (url: string, options?: Object): Promise<One | Two> => {
  const res = await fetch(url, options);
  const data = await res.json();
  return data;
};

но этот подход не совсем хорош, потому что каждый раз, когда вы выбираете другой источник данных, вам придется создавать новый интерфейс и добавлять его во вспомогательную функцию.

Итак, как я могу сделать эту функцию fetchingData более динамичной при возврате типизированного промиса?

Спасибо за вашу помощь


person Khris_Al    schedule 31.03.2021    source источник
comment
Попробуйте использовать универсальные шаблоны.   -  person vadimk7    schedule 31.03.2021
comment
Зависит ли тип возвращаемого значения в типизированном промисе от какого-либо ввода или контекста, вызывающего его?   -  person Shivam Singla    schedule 31.03.2021
comment
Я обновил свой ответ двумя возможными решениями. Пожалуйста, посмотрите   -  person Amir Saleem    schedule 31.03.2021


Ответы (2)


По моему мнению, лучшим подходом к проектированию было бы создание методов с конкретными именами вместо одного общего метода. Имя вашей функции должно говорить о том, что она делает. Он должен быть конкретным. Я бы пошел со следующим дизайном.

class ApiService {

  // method to fetch states from the API call
  private static fetchState(url: string, options: StateOptions): Promise<State[]> {
      return ApiService.fetchData(url, options);
  }
  
  // private method, only accessible in ApiService class
  private static async fetchData(url: string, options?: any): Promise<any> {
      const res = await fetch(url, options);
      const data = await res.json();
      return data;
  }

}

Нехорошо помещать все ваши вызовы API в один класс, вы можете классифицировать их, расширив класс APIService, сделав метод fetchData protected.

Преимущества вышеуказанного подхода

  1. Интерфейсы для опций и возвращаемого типа могут быть определены
  2. имена функций относятся к фактическому вызову API, помогают в отладке и повышают читабельность кода.
  3. Особые случаи, такие как предварительная обработка данных перед вызовом API или определение констант, могут выполняться в конкретной функции. Например, если ваш API состояния требует, чтобы вы передавали язык как en, лучше жестко закодировать это в вашем методе ApiService.fetchState, а не передавать его в аргумент при каждом вызове функции.

Я выбрал объектно-ориентированный подход, вы можете реализовать то же самое, используя функциональный подход. Но главное в том, что не используйте общий метод везде в своем коде, вы столкнетесь с проблемами, а масштабирование и обслуживание будут очень сложными.

Это мое личное мнение из собственного опыта.

Теперь, что касается вашего вопроса.

Как создать функцию, которая динамически возвращает тип Promise?

Вы можете сделать это, используя универсальные шаблоны в Typescript.

async function fetchData<T>(url: string): Promise<T> {
    const result: any = {};
    return result;
}

interface State {
    code: string;
    name: string;
}

interface Country {
    code: string;
    name: string;
}

const fetchStates = fetchData<State[]>("/fetch/state");
const fetchCountry = fetchData<Country[]>("/fetch/country");

Link to TS Playground

person Amir Saleem    schedule 31.03.2021

Вы можете сделать это так. If you want to add another type you can just change or add in type T. Проверить игровую площадку Ts

 type T = string | number;
    const fetchingData = async (url: string, options?: Object): Promise<T> => {
      const res = await fetch(url, options);
      const data = await res.json();
      return data;
    };
person Syed Mohib Uddin    schedule 31.03.2021