Есть ли способ получить тип возвращаемого значения функции генератора? - PullRequest
2 голосов
/ 11 марта 2019

Я хочу получить тип возврата функции генератора.
Например

function* test(){
  yield 'a';
  yield 123;

  return true;
}

// what I'm trying to get
type A = GetGeneratorReturn<test>; // -> A has type boolean

То, что я сейчас нахожусь.

type B = ReturnType<ReturnType<typeof test>['next']>['value'];
// B has type `true | "a" | 123`

(я думал, что смогу получить возвращаемый тип, если получу первый предмет типа Union B)

1 Ответ

2 голосов
/ 11 марта 2019

Существует открытый выпуск , в котором говорится об этой проблеме среди других, но она довольно старая и не похоже, что кто-то к ней стремится, поскольку некоторые другие проблемы уже решены.Я вижу последние упоминания об этом тут и там.Кажется, самая актуальная проблема - это эта .Если это важно для вас, вы можете перейти на GitHub и дать ответы на эти вопросы.

На данный момент кажется, что типизация генератора в TypeScript дает вам доступ только к недифференцированному объединению типов yield и типа return.И, к сожалению, вы не можете полагаться на заказ типа объединения.Это деталь реализации компилятора;поскольку X | Y эквивалентно Y | X, компилятор может сменить одно на другое.И иногда это так:

function* test() {
  yield 'a';
  yield 123;
  return true;
} // function test(): IterableIterator<true | "a" | 123>

function* oops() {
  yield true;
  yield 123;
  return 'a'
} // function oops(): IterableIterator<true | "a" | 123>

Тип возврата oops() равен точно так же , что и тип возврата test().Это означает, что ваша идея извлечь первый / последний элемент объединения не является стартовой.

Возможно, есть обходной путь, который поможет, особенно если вы можете возиться с определением генератора и не обращать внимания на некоторые фантомные типы, плавающие вокруг:

type Returnable<T> = { __returnedType?: T } & T
const ret = <T>(t: T) => t as Returnable<T>;
type GeneratorReturn<T extends (...args: any) => IterableIterator<any>> =
  ReturnType<T> extends IterableIterator<infer I> ?
  NonNullable<Extract<I, Returnable<unknown>>['__returnedType']> : never

function* test() {
  yield 'a';
  yield 123;
  return ret(true); // only use ret() here
} 

function* oops() {
  yield true;
  yield 123;
  return ret('a'); // only use ret() here
} 

type TestRet = GeneratorReturn<typeof test>; // true
type OopsRet = GeneratorReturn<typeof oops>; // "a"

Который работает, насколько это возможноидет, но не может быть то, что вы хотите преследовать.Ну что ж, извините, что не могу найти лучшего ответа здесьУдачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...