Last active
May 5, 2023 03:53
-
-
Save lokshunhung/d08986dff5923d92b3971b615480d025 to your computer and use it in GitHub Desktop.
TS: consume iterable using generator `yield`s
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // consumeIterable.ts | |
| type NoInfer<T> = [T][T extends any ? 0 : never]; // https://github.com/millsp/ts-toolbelt/blob/319e551/sources/Function/NoInfer.ts#L27 | |
| type AnyIteratorResult = IteratorResult<any, any>; | |
| function consumeIterable<T>( | |
| producer: Iterable<T>, | |
| consumer: () => Generator<undefined, void, NoInfer<T>> | |
| ): void { | |
| const produce = producer[Symbol.iterator](); | |
| const consume = consumer(); | |
| const exhaustive = arguments[2] ?? true; | |
| let produceResult: AnyIteratorResult = { value: undefined }; | |
| let consumeResult: AnyIteratorResult; | |
| // prettier-ignore | |
| while (( | |
| consumeResult = consume.next(produceResult.value), | |
| produceResult = produce.next(), | |
| !consumeResult.done && !produceResult.done | |
| )); | |
| switch (true) { | |
| case !consumeResult.done: | |
| throw new Error("[consumeIterable] producer has ended but consumer contains extra `yield` statements"); | |
| case !produceResult.done && exhaustive: | |
| throw new Error("[consumeIterable] producer not ended but consumer contains no more `yield` statements"); | |
| } | |
| } | |
| consumeIterable.nonExaustive = function consumeIterableNonExhaustive<T>( | |
| producer: Iterable<T>, | |
| consumer: () => Generator<undefined, void, NoInfer<T>>, | |
| ): void { | |
| return consumeIterable.call(null, producer, consumer, false); | |
| }; | |
| // playground.ts | |
| function expect(_) { | |
| console.log(`expect`, _); | |
| return { | |
| toBe(__) { | |
| console.assert(_ === __, `${_} !== ${__}`); | |
| }, | |
| }; | |
| } | |
| consumeIterable([1, 2], function* () { | |
| expect(yield).toBe(1); | |
| expect(yield).toBe(2); | |
| // expect(yield).toBe(3); | |
| }); | |
| consumeIterable.nonExaustive([1, 2, 3], function* () { | |
| expect(yield).toBe(1); | |
| expect(yield).toBe(2); | |
| // expect(yield).toBe(3); | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment