Flow делает тип обещания - PullRequest
       5

Flow делает тип обещания

0 голосов
/ 15 января 2020

Что ж, в моем приложении я пытаюсь добавить тип потока к ватерлинии orm.

Для этого я попытался добавить новый класс "_DeferredPromise", который является thenable (или promise , поскольку он работает с promise.all и await), однако он добавляет несколько дополнительных функций, позволяющих объединять запросы к базе данных. Обычно подпись для таблицы в ORM будет выглядеть следующим образом:

type DatabaseORMTy<T> = {
  find: (number | {+[string]: mixed}) => _DeferredPromiseTy<$Array<T>>,
  //...
}

И deferredPromise:

type _DeferredPromiseTy<T> = {
  ...Promise<T>,
  fetch: () => _DeferredPromiseTy<T>,
  limit: (string|number) => _DeferredPromiseTy<T>,
  select: (?$ReadOnlyArray<string>) => _DeferredPromiseTy<T>,
  skip: (number) => _DeferredPromiseTy<T>,
  sort: (string) => _DeferredPromiseTy<T>,
  //and more
}

Проблема заключается в следующем: я не могу позволить потоку действовать так, как если бы он был отложен обещания - это обещания , только с несколькими дополнительными функциями. Я попытался добавить подпись обещания с $Exact<Promise> - что заставляет поток жаловаться, что вы не можете дать точное обещание. Я попытался добавить их, используя = Promise & {...}, и попытался выше.

Но все они показывают ошибку в использовании:

const data:T = await myTable.find(1).limit(1); //would find the entry with id=1, and at most 1 entry.

Появляется следующая ошибка:

Error: Cannot call await with `find(...)` bound to `p` because  `_DeferredPromiseTy` [1] is incompatible with  `Promise` [2].

Как сделать пользовательский тип совместимым с Promise?

Например, в попытке Flow (я замечаю, что там сообщение об ошибке отличается): fiddle

1 Ответ

1 голос
/ 17 января 2020

Flow предоставляет Promise специальную обработку и в настоящее время не позволяет использовать await с пользовательскими таблицами. Однако вы можете расширить Promise, и Flow позволяет использовать экземпляры подкласса как Promise s.

У вас есть пара вариантов:

Вы можете использовать declare class, что заставляет Flow думать, что класс такого типа доступен. Недостатком здесь является то, что Flow позволит вам делать такие вещи, как x instanceof _DeferredPromiseTy, или пытаться построить его, даже если в действительности такого класса не существует.

declare class _DeferredPromiseTy<T> extends Promise<T> {
  fetch: () => _DeferredPromiseTy<T>,
  limit: (string|number) => _DeferredPromiseTy<T>,
  select: (?$ReadOnlyArray<string>) => _DeferredPromiseTy<T>,
  skip: (number) => _DeferredPromiseTy<T>,
  sort: (string) => _DeferredPromiseTy<T>,
  //and more
};

( детская площадка )

Чтобы решить эту проблему, вы действительно можете определить такой класс. Недостатком здесь является то, что если вы просто пытаетесь добавить типы в существующую кодовую базу, она может быть не структурирована таким образом, чтобы это было практично:

class _DeferredPromiseTy<T> extends Promise<T> {
  fetch(): _DeferredPromiseTy<T> { return this; }
  limit(x: string|number): _DeferredPromiseTy<T> { return this; }
  //and more
};

( детская площадка )

...