Unraveling the mystery of unwrapping an async or sync generator

Is there a way to extract the inner return type of an async generator or sync generator?

In other words, I'm searching for something similar to Awaited which is used for promises.

For promises, I would typically do:

async function foo() {
}

let returnValue: Awaited<ReturnType<typeof foo>>;

When it comes to generators, I'm trying to find:

async function* foo() {
}

function* bar() {
}

let returnValue: ???<ReturnType<typeof foo | typeof bar>>;

Answer №1

es2015.iterable includes the Generator type that allows for inferring yield values:

function* foo() {
  yield 1;
  yield 2;
}

function* bar() {
  yield 3;
  yield 4;
}

type GeneratorValue<G extends (...arg: any[]) => any> = ReturnType<G> extends Generator<infer X> ? X : never;

type fooG = GeneratorValue<typeof foo | typeof bar> // 1 | 2 | 3 | 4

Interactive demo

Trying to type an async generator using this method didn't work, and extending an AsyncGenerator type from existing interfaces proved challenging but potentially achievable.

Answer №2

If you want to create your own utility types, you can follow a similar approach to how the ReturnType type is implemented. Instead of inferring the entire return type, focus on inferring the type arguments for the AsyncGenerator and Generator generic types. These types represent what generator and async generator functions return in TypeScript:

type GenYieldType<T extends (...args: any) => Generator<any, any, any>> =
  T extends (...args: any) => Generator<infer R, any, any> ? R : never;

type AsyncGenYieldType<T extends (...args: any) => AsyncGenerator<any, any, any>> =
  T extends (...args: any) => AsyncGenerator<infer R, any, any> ? R : never

Let's put it to the test:

async function* foo() { yield "a"; yield "b"; }
type FooYield = AsyncGenYieldType<typeof foo>
//   ^? type FooYield = "a" | "b"
    
function* bar() { yield "c"; yield "d"; }
type BarYield = GenYieldType<typeof bar>
//   ^? type BarYield = "c" | "d"

Looks like everything is working as expected.

Check out the playground link for more code examples

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The Express API controller is unexpectedly receiving empty strings

I am encountering an issue where my API is receiving an empty string instead of the expected data when I send post requests with a single string in the body. Below are the client, server, and controller components involved: Function call (client): const ...

What could be causing my TypeScript code to not be recognized as CommonJS?

I rely on a dependency that is transpiled to ES6. My goal is to leverage ES2019 features in my own code. Ultimately, I aim to output ES6. This is how I set up my tsconfig { "compilerOptions": { "module": "CommonJS" ...

A class member is not permitted to include the 'const' keyword

Having trouble with my ts code as I try to create a constant that can be easily changed by just modifying a simple element - but keep encountering the error that says "A class member cannot have the 'const' keyword." Here's the code snippet ...

Sharing information from the $mdDialog child component to the parent component

I have a scenario where I am using one app controller to call a model window and need to pass data from the $mdDialog model window to the app controller. How can I achieve this? //parent Controller class appCtrl implements IappSettings { public displa ...

Is it possible to export all types/interfaces from .d.ts files within multiple folders using index.ts in a React TypeScript project?

In my current React project, I am managing multiple configuration folders: -config -api/ |index.ts |types.d.ts -routes/ |index.ts |types.d.ts ... For example, in the api/index.ts file, I can import necessary types using import {SomeTyp ...

Having difficulty accessing an element within ng-template during the unit test writing process with Jasmine

I am encountering an issue when trying to access a button inside an ng-container in my testing environment. Despite manually setting the value of the ngIf condition to true, the elements inside are not being rendered. Here is what I have attempted so far: ...

Tips for validating and narrowing a type in TypeScript using isNull instead of isNonNullable

I want to implement a universal type guard for entities returned from an API. The goal is to handle any null | undefined values by throwing an HttpStatus.NOT_FOUND error. Initially, I tried the following approach: export const entityOr404 = <T>(entit ...

Searching in TypeScript tables with Angular's search bar

I've successfully completed a basic CRUD application, but now I need to incorporate a Search Bar that can filter my table and display rows with matching letters. I'm unsure how to approach this in my component. I've seen examples using pipe ...

Implementing a variable for an array in Angular 4: A step-by-step guide

I need help determining the correct value for skill.team[variable here].name in Angular, where all team names are retrieved from the skill. Below is the code snippet: HTML <select [(ngModel)]="skill.teams[1].name" name="teamName" id="teamName" class= ...

Watching - transforming / combining

I am a beginner when it comes to working with Observables. Here's the Effect that I am using: My goal is to dispatch the PositionUpdateAction or PositionFailedAction before the SunriseSunsetAction is dispatched. Currently, what happens is that the r ...

What are the best practices for utilizing an array of routes?

I'm new to working with react but I noticed something strange. My routes are currently set up like this: <Main> <Route exact path="/home" component={Home} /> <Route exact path="/home1" com ...

Tips for properly implementing an enum in TypeScript when using the React useState hook

What's the correct way to utilize my useState hook? I have this enum type: export enum Status { PENDING = 'pending', SUCCESS = 'success', ERROR = 'error', } And the useState hook: const [isValid, setIsValid] = use ...

Transform the string property extracted from the API into a JSON object

When making a request to an API, the data returned to the front end is in the following format: { name: 'Fred', data: [{'name': '"10\\" x 45\\" Nice Shirts (2-pack)"', 'price' ...

Checkbox Event Restricts Access to a Single Class Variable

As a beginner in AngularJS (just diving in this week), I've encountered an issue with a checkbox input connected to an ng-change event. <input type="checkbox" ng-model="vm.hasCondoKey" ng-change="vm.onKeyCheckboxChange()" /> The ng-change even ...

Possible Problems that Could Occur if I Give a Custom MUI Component the Same Name as the Default Component?

As I dive into a ReactJS project utilizing MUI, I find myself tasked with theming components to align with our company's UX design guidelines. Many components can be easily customized using the MUI theme provider. However, certain components require ...

How can you verify the value of a disabled HTML input element in TestCafe using Typescript?

TestCafe Typescript - how to verify the value of a disabled HTML input element? Despite being disabled for user interaction, I want to ensure that this element still holds the anticipated value. example public async checksomething(text: string) { co ...

Error message: Conflicting type declarations across multiple files

I am facing a challenge with my TypeScript 'snippets' project. It seems that multiple .ts files contain type names (like Foo) that are the same. //file-a.ts type Foo = { } //file-b.ts type Foo = { } When attempting to compile, I encounter ...

What prevents us from returning Observable.of(false) in the catch block within the canActivate function?

In order to protect certain routes (admin), I utilize the canActivate feature. In this scenario, I employ an authGuard class/function: The issue arises when attempting to return an observable of boolean using: return Observable.of(false);. This approach d ...

Enhancing view with Typescript progressions

My current view only displays a loader.gif and a message to the user. I am looking to enhance the user experience by adding a progress indicator, such as "Processing 1 of 50", during the data update process. The ts class interacts with a data service layer ...

Is there a way to verify within the "if" statement without repeating the code?

Is there a way in javascript (or typescript) to prevent redundant object rewriting within an if statement condition? For example: if (A != null || A != B) { // do something here } // can it be done like this: if (A != null || != B) { // avoid repeating ...