-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Trouble implementing .then #33416
Labels
Rescheduled
This issue was previously scheduled to an earlier milestone
Working as Intended
The behavior described is the intended behavior; this is not a bug
Milestone
Comments
RyanCavanaugh
added
the
Needs Investigation
This issue needs a team member to investigate its status.
label
Sep 16, 2019
RyanCavanaugh
added
the
Rescheduled
This issue was previously scheduled to an earlier milestone
label
Aug 31, 2020
yukihirop
added a commit
to yukihirop/rue
that referenced
this issue
Mar 31, 2021
yukihirop
added a commit
to yukihirop/rue
that referenced
this issue
Mar 31, 2021
This doesn't seem to be a bug in TypeScript, but rather an issue with the definition of the type. The /**
* Promise.prototype.then onfufilled callback type.
*/
type Fulfilled<R, T> = ((result: R) => T | PromiseLike<T>) | null;
/**
* Promise.then onrejected callback type.
*/
type Rejected<E> = ((reason: any) => E | PromiseLike<E>) | null;
class Waiter<T, TReturn, TNext> implements PromiseLike<TReturn> {
source: AsyncGenerator<T, TReturn, TNext | undefined>;
constructor(
source: () => AsyncGenerator<T, TReturn, TNext | undefined>,
) {
this.source = source();
}
then<TResult1, TResult2 = TResult1>(onfufilled?: Fulfilled<TReturn, TResult1>, onrejected?: Rejected<TResult2>): Promise<TResult1 | TResult2> {
return this.implementation().then(onfufilled, onrejected);
}
private async implementation(): Promise<TReturn> {
// Drain the async iterator by hand since for-await-of would
// discard the returned value.
while (true) {
// NOTE(rbuckton): The `T` in `AsyncGenerator<T, ...>` is never
// sent: ---------------------v
const { done, value } = await this.source.next();
// We know value will be a TReturn as the async iterator
// has already been exhausted
if (done) return value as TReturn
}
}
}
async function main() {
let waiter = new Waiter(async function* gen() {
yield 123;
return "abc";
});
try {
let result = await waiter;
console.log(
`expect ${JSON.stringify(result)} to equal "abc"`,
result === "abc"
);
} catch (error) {
console.error("Oh no", error)
}
let other = await waiter.then(() => 123);
console.log(`expect ${JSON.stringify(other)} to equal 123`, other === 123);
}
main().catch(console.error) |
rbuckton
added
Working as Intended
The behavior described is the intended behavior; this is not a bug
and removed
Needs Investigation
This issue needs a team member to investigate its status.
labels
Dec 6, 2021
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
Rescheduled
This issue was previously scheduled to an earlier milestone
Working as Intended
The behavior described is the intended behavior; this is not a bug
[email protected]
I added to libraries:
$ tsc --lib es2018,dom --target es2018 test-case.ts
.Search Terms:
AsyncIterator, AsyncGenerator, Then, Promise, PromiseLike
Code
Expected behavior:
The code to compile, and correctly infer the return type for
other
in the example above.Running it with node gives the correct output:
Actual behavior:
When poking around in VS Code it correctly infers that
await waiter
is a string, which is nice. Butawait waiter.then(() => 123)
becomes unknown instead of number. I'm guessing it's because of the type error above, but still pretty amazing that it can infer anything at all.I also tried inlining the definitions of
Fulfilled
andRejected
, but no dice. I also tried changing all type parameters toT
, but again nothing:Playground Link
Related Issues:
#16993
#15599
#33239
#31264
The text was updated successfully, but these errors were encountered: