Как заставить машинописный текст думать, что обещание <T>разрешено как Type T - PullRequest
0 голосов
/ 27 мая 2020

Я новичок в машинописном тексте, и я что-то создаю и столкнулся с проблемой, которой никогда не было, когда я использовал javascript.

Предположим, что у нас есть функция async, которая возвращает Promise<ResultSet>

interface ResultSet {
  status: number; // 0 for success 1 for failure
  data?: any;
}

const getDataFromServer = async (parameter: string): Promise<ResultSet> => {
   const response = await fetch(<--Prameters-->);
   return await response.json();
}

Он всегда возвращает значение как Promise.

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

const storeData = async (parameter: string): number => {
  const result = await getDataFromServer(parameter);
  if (result.status == 0) {
    SOME_GLOBAL_VARIABLE.setState({ data: result.data });
  }
  return result.status;
}

Как и следовало ожидать, приведенное выше определение функции выдает ошибку около async (parameter: string): number, потому что функция должна возвращать Promise в том виде, в каком она есть async. Так что он должен быть ниже,

const storeData = async (parameter: string): Promise<number> => {
  const result = await getDataFromServer(parameter);
  if (result.status == 0) {
    SOME_GLOBAL_VARIABLE.setState({ data: result.data });
  }
  return result.status;
}

Проблема начинается с этого. Причина возврата функции - Promise, интерфейсы всех других функций, связанные с этим, должны определять этот статус результата как Promise<number>, а не number. И это будет глобально воздействовать на весь серверный код. Кроме того, SOME_GLOBAL_VARIABLE s data также нужно набирать как Promise<T>.

Насколько я знаю, нет способа преобразовать объект обещания в обычный объект.

I хочу сократить эту бесконечную цепочку обещаний. Там в любом случае? или это просто недоразумение? Даже замена async ~ await на then() ~ catch() также не удалась, потому что кажется, что она также возвращает Promise.

Гарантия Promise, успешно разрешено это значение или нет. Но в какой-то момент это уже гарантировано как Resolve. Но нет способа справиться с этой ситуацией.

Как я могу справиться с этой ситуацией? Это действительно частый случай при использовании машинописного текста. Но я не знаю, как это сделать.

Ответы [ 2 ]

2 голосов
/ 27 мая 2020

Это не отличается от обычного JavaScript, просто TypeScript дает ему имя.

Короткий ответ - нет, вы не можете преобразовать обещание объекта в сам объект. Это происходит не из-за TypeScript, а из-за API-интерфейса обещаний (или самой природы асинхронного кода).

После работы с обещаниями / async / await единственное место, где вы можете получить доступ к обещанному типу, находится внутри обработчик then (или после использования await):

// Using promises
storeData().then((result: number) => { /* result is a number here, not a promise of a number */ });

// Using async / await
const result = await storeData(); // again, result is a number, not a promise of a number

Таким образом, чтобы избежать выполнения всего кода, основанного на обещании, вам необходимо вызвать его из обработчика then (или после await ):

// An example of a promise-less function somewhere in your code
const someOtherFunction = (result: number) => { /* do something with your result */ };

storeData().then(result => {
  // this works since result is a number here
  someOtherFunction(result);
});

Конечно, вы можете написать абстракцию, которая обертывает обещание, объект, скажем, со свойством value, который ожидает обещания и устанавливает value на себя после разрешения. Однако вам все равно придется ждать разрешения обещания, чтобы получить значение разрешения.

1 голос
/ 27 мая 2020

Сегодня я ел гамбургеры. У нас не было булочек, поэтому жена пошла покупать. Я не мог собрать гамбургеры, пока жена не вернулась из магазина с булочками. Соответственно, мне также пришлось подождать, чтобы съесть булочки, чтобы sh накрыть тарелку и т. Д. c.

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

Как указывает ответ @ ján-jakub-naništa, в javascript ситуация точно такая же, как и в машинописном тексте; просто машинописный текст делает немного более очевидным, что происходит.

Есть много способов выйти из этой цепочки асинхронных c функций, но в конечном итоге вам все равно придется ждать значения. Лучшее, что я могу предложить, - это попытаться максимально изолировать асинхронный код; если у вас есть, например, Promise<number>, разрешите это обещание вызвать функцию, которая просто принимает number. Таким образом вы можете избежать заражения вашего кода ненужными типами Promise.

...