Существует открытый выпуск , в котором говорится об этой проблеме среди других, но она довольно старая и не похоже, что кто-то к ней стремится, поскольку некоторые другие проблемы уже решены.Я вижу последние упоминания об этом тут и там.Кажется, самая актуальная проблема - это эта .Если это важно для вас, вы можете перейти на 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"
Который работает, насколько это возможноидет, но не может быть то, что вы хотите преследовать.Ну что ж, извините, что не могу найти лучшего ответа здесьУдачи!