Skip to content

Commit

Permalink
Add IterableElement type (#110)
Browse files Browse the repository at this point in the history
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
  • Loading branch information
Elmer Bulthuis and sindresorhus committed Sep 29, 2020
1 parent bb0d215 commit 0e8f4e3
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 0 deletions.
1 change: 1 addition & 0 deletions index.d.ts
Expand Up @@ -24,6 +24,7 @@ export {ConditionalPick} from './source/conditional-pick';
export {UnionToIntersection} from './source/union-to-intersection';
export {Stringified} from './source/stringified';
export {FixedLengthArray} from './source/fixed-length-array';
export {IterableElement} from './source/iterable-element';

// Miscellaneous
export {PackageJson} from './source/package-json';
Expand Down
1 change: 1 addition & 0 deletions readme.md
Expand Up @@ -83,6 +83,7 @@ Click the type names for complete docs.
- [`UnionToIntersection`](source/union-to-intersection.d.ts) - Convert a union type to an intersection type.
- [`Stringified`](source/stringified.d.ts) - Create a type with the keys of the given type changed to `string` type.
- [`FixedLengthArray`](source/fixed-length-array.d.ts) - Create a type that represents an array of the given type and length.
- [`IterableElement`](source/iterable-element.d.ts) - Get the element type of an `Iterable`/`AsyncIterable`. For example, an array or a generator.

### Miscellaneous

Expand Down
46 changes: 46 additions & 0 deletions source/iterable-element.d.ts
@@ -0,0 +1,46 @@
/**
Get the element type of an `Iterable`/`AsyncIterable`. For example, an array or a generator.
This can be useful, for example, if you want to get the type that is yielded in a generator function. Often the return type of those functions are not specified.
This type works with both `Iterable`s and `AsyncIterable`s, so it can be use with synchronous and asynchronous generators.
Here is an example of `IterableElement` in action with a generator function:
@example
```
function * iAmGenerator() {
yield 1;
yield 2;
}
type MeNumber = IterableElement<ReturnType<typeof iAmGenerator>>
```
And here is an example with an async generator:
@example
```
async function * iAmGeneratorAsync() {
yield 'hi';
yield true;
}
type MeStringOrBoolean = IterableElement<ReturnType<typeof iAmGeneratorAsync>>
```
Many types in JavaScript/TypeScript are iterables. This type works on all types that implement those interfaces. For example, `Array`, `Set`, `Map`, `stream.Readable`, etc.
An example with an array of strings:
@example
```
type MeString = IterableElement<string[]>
```
*/
export type IterableElement<TargetIterable> =
TargetIterable extends Iterable<infer ElementType> ?
ElementType :
TargetIterable extends AsyncIterable<infer ElementType> ?
ElementType :
never;
20 changes: 20 additions & 0 deletions test-d/iterable-element.ts
@@ -0,0 +1,20 @@
import {IterableElement} from '../source/iterable-element';
import {expectType} from 'tsd';

declare const iterableElement: IterableElement<ReturnType<typeof secretGenerator>>;
expectType<1 | 'two'>(iterableElement);

declare const iterableElementAsync: IterableElement<ReturnType<typeof secretGeneratorAsync>>;
expectType<true | Date>(iterableElementAsync);

// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
function * secretGenerator() {
yield 1;
yield 'two';
}

// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
async function * secretGeneratorAsync() {
yield true;
yield new Date();
}

0 comments on commit 0e8f4e3

Please sign in to comment.