Created
February 16, 2022 17:45
-
-
Save jtbandes/5360453f2895cbf552ec71b240b53009 to your computer and use it in GitHub Desktop.
This file contains 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
type MaybeAwait<P> = P extends Promise<infer T> ? T : P; | |
function maybeAsync<Args extends unknown[], TYield, TReturn>( | |
body: (...args: Args) => Generator<TYield, TReturn, MaybeAwait<TYield>> | |
): (...args: Args) => (TYield extends Promise<infer _P> ? Promise<TReturn> : TReturn); | |
function maybeAsync<Args extends unknown[], TYield, TReturn>( | |
body: (...args: Args) => Generator<TYield, TReturn, MaybeAwait<TYield>> | |
): (...args: Args) => (Promise<TReturn> | TReturn) { | |
return (...args: Args) => { | |
let gen = body(...args); | |
function run(...args: [] | [TYield extends Promise<infer P> ? P : TYield]): Promise<TReturn> | TReturn { | |
let result = gen.next(...args); | |
while (!result.done) { | |
if (result.value instanceof Promise) { | |
return result.value.then(run); | |
} else { | |
result = gen.next(result.value as MaybeAwait<TYield>); // https://github.com/microsoft/TypeScript/issues/47901 | |
} | |
} | |
return result.value; | |
} | |
return run(); | |
} | |
} | |
interface Filelike { | |
read(offset: number, length: number): Promise<Uint8Array> | Uint8Array; | |
} | |
class Adder<F extends Filelike> { | |
constructor(private file: F) {} | |
*_sum(): Generator<ReturnType<F['read']>, number, MaybeAwait<ReturnType<F['read']>>> { | |
let sum = 0; | |
const bytes = yield (this.file.read(0, 3) as ReturnType<F['read']>); // https://github.com/microsoft/TypeScript/issues/47900 | |
sum = bytes.reduce((acc, val) => acc + val, sum); | |
const bytes2 = yield (this.file.read(10, 3) as ReturnType<F['read']>); // https://github.com/microsoft/TypeScript/issues/47900 | |
sum = bytes2.reduce((acc, val) => acc + val, sum); | |
return sum; | |
} | |
sum = maybeAsync(this._sum.bind(this)); | |
} | |
function makeArray(start: number, len: number) { | |
let result = new Uint8Array(len); | |
for (let i = 0; i < len; i++) { | |
result[i] = start + i; | |
} | |
return result; | |
} | |
let sumSync: number = new Adder({ read: (start, len) => makeArray(start, len) }).sum(); | |
console.log("sum1", sumSync); | |
let sumAsync: Promise<number> = new Adder({ read: async (start, len) => makeArray(start, len) }).sum(); | |
sumAsync.then((val) => console.log("sum2", val)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment