-
Notifications
You must be signed in to change notification settings - Fork 31
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
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
Idea: Task
#25
Comments
Spitballing some of the conversion functions here: type Task<T, E> = Resolved<T, E> | Rejected<T, E>;
function fromPromise<T, E>(
promise: PromiseLike<T>,
resolved: (t: T) => Resolved<T, E>,
rejected: (err: unknown) => Rejected<T, E>
): Task<T, E> {
let task: Task<T, E>;
promise
.then(value => {
task = resolved(value);
})
.catch(error => {
task = rejected(error);
});
return task;
}
function toPromise<T, E>(task: Task<T, E>): Promise<T> {
return new Promise((resolve, reject) => {
task.match({
Resolved: resolve,
Rejected: reject,
});
});
} Note that this is effectively sugar for |
How about calling it |
@belfz yeah, I used
In terms of which to land on, I intend to spend some time thinking about the semantics of the operation, as I did in choosing the I don't actually particularly love More to come! |
Ha, I see your point! I'm not a huge fan of |
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
Spitballing here a bit: I've been thinking about a type named
Future
orTask
as a possibly-useful thing to add to the library. This is interesting to me in that it's really useful to have some tools in the space thatPromise
lives in—namely, asynchronous operations and computations—but with different tradeoffs thanPromise
made.For those who might not have thought about what
Promise
does differently from, say,Result
orMaybe
before, there are a bunch of differences, some necessary consequences of how JS works and some less so. The ones that immediately come to mind for me:Promise
combines what True Myth's types callmap
andandThen
into a single function:then
. In terms of type signatures, the way to think about it is thatmap
takes a function whose signature is(t: T) -> U
and gives you back aMaybe<U>
, andandThen
takes a function whose signature is(t: T) -> Maybe<U>
, and gives you back aMaybe<U>
. The same thing goes forResult
.Promise#then
, however, can take either one. That is, if you givethen
a function with the signature(t: T) -> U
, you'll get back aPromise<U>
, and if you givethen
a function with the signature(t: T) -> Promise<U>
you'll also get back aPromise<U>
.This is a choice made for convenience and a sort of accident of history rolled into one, and I'm not at all interested in relitigating it. It is what it is in JavaScript today. More interesting to me is whether we can provide a better interface on top of it.
Promise
to have two types in play—the return type and the type of the error that will show up in thecatch
arm—but unfortunately, the catch argument is (correctly) typed asany
in TypeScript. (Properly, given TS 3.0, we’d probably dounknown
, but TS sensibly tries to avoid backwards-incompatible changes in the standard library types.) This is becausePromise#catch
has to capture any thrown exception along with any rejection created withPromise.reject
.As far as I can see this is a fundamental problem facing any kind of
Task.fromPromise
function, but in principle it’s solveable. You just need a type that takes theany
(or better,unknown
) type handed to thecatch
function and converts it to the desired errorE
type:(error: unknown) => E
.One other note: like
Promise
itself, and unlikeMaybe
andResult
, aTask
captures a kind of computation you can’t (synchronously) exit from! The whole point is to model asynchronous behaviors.The text was updated successfully, but these errors were encountered: