Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

.await has wrong type? #457

Closed
jasonkuhrt opened this issue Jun 19, 2017 · 13 comments
Closed

.await has wrong type? #457

jasonkuhrt opened this issue Jun 19, 2017 · 13 comments

Comments

@jasonkuhrt
Copy link

jasonkuhrt commented Jun 19, 2017

Summary

I think the TypeScript type for Most.await is problematic. Consider this code:

  return Most
    .periodic(queueSettings.WaitTimeSeconds / 1000)
    .map(() => pull(settings.queue, queueSettings))
    .await() // should be awaitPromises but TypeScript definition doesn't accept that yet...
    .concatMap((data: AWS.SQS.ReceiveMessageResult) =>
      Most.from(data.messages.map(process)),
    )
    .multicast()

Expected result

It should return a Stream<Change>.

Actual Result

It instead returns a Stream<{}>. This is because of await which has a return value of Stream<{}>.

Versions

  • most.js:
    ^1.4.0

I will try to come back with a PR or failing that a simplified repro.

@briancavalier
Copy link
Member

@jasonkuhrt I'm not really sure a correct type definition can be written for the method form of .await(). See this note. AFAIK, there's no way in TS to express "this method can only be called on a this whose value type is Promise<B>".

I don't know why TS would infer a type of {} for B in this case, though. Maybe @TylorS has some fresh insight on it.

@briancavalier
Copy link
Member

Ah I just saw your comment about awaitPromises being missing from the TS defs, too! Good catch. We should def fix that as well.

@jasonkuhrt
Copy link
Author

for the method form of .await()

Oh but function form yes?

// Note: Without higher-kinded types, this type cannot be written properly

What would higher-kinded types look like in this case? FlowType has the same limitation?

@jasonkuhrt
Copy link
Author

@briancavalier
Copy link
Member

Yep, it's possible for the function form. The type def shows how await "removes" the Promise "wrapper" from every event in the stream.

What would higher-kinded types look like in this case?

In this case, there would need to be a way to express that the .await method is only valid for a this which is Stream<Promise<A>>. Maybe HKTs aren't strictly necessary for that, but I don't know of any way to express it in TS.

FlowType has the same limitation?

It does indeed. I'm not aware of any way to do it Flow, either.

@gcanti has done some pretty amazing work in simulating HKTs and more recently, representing them using property types (I think that's what they're called) in TS. It seems like applying his patterns may require a fairly significant restructuring of most.js, but I really have no idea right now.

@jasonkuhrt
Copy link
Author

jasonkuhrt commented Jun 20, 2017

@briancavalier I've never used compse with most before but the API doesn't appear to be curried which does hinder its practicality as a replacement for method chains IMHO.

@gcanti
Copy link

gcanti commented Jun 20, 2017

there's no way in TS to express "this method can only be called on a this whose value type is Promise<B>"

Maybe this can be helpful

declare class Stream<A> {
  map<B>(f: (a: A) => B): Stream<B>
  // you can define a type annotation for this
  await<B>(this: Stream<Promise<B>>): Stream<B>
  // etc...
}

new Stream<number>().await() // error
new Stream<Promise<number>>().await() // ok
new Stream<string>().map(s => Promise.resolve(s.length)).await() // ok

@briancavalier
Copy link
Member

Thanks, @gcanti. I didn't know type constraints on this existed as a feature in TS! Seems like a great solution. Do either of you know how new that feature is? i.e. what version of TS? If it is "too new", we may need to wait a bit until that version of TypeScript is in wide use.

Looks like there's at least some discussion about adding an equivalent feature to Flow.

@briancavalier
Copy link
Member

the API doesn't appear to be curried

Yeah, in 1.x it isn't. In @most/core, it is, and it will be in most 2.0, since it'll be based on @most/core.

@gcanti
Copy link

gcanti commented Jun 20, 2017

@briancavalier
Copy link
Member

@gcanti Great, seems safe to require it then. Thanks for the help 👍

@jasonkuhrt If you're still up for a PR, I'd certainly welcome one that applies a this constraint for .await() and adds awaitPromises alias for function and method.

@jasonkuhrt
Copy link
Author

@briancavalier I'll give it a go! I'll try to do it this week.

@briancavalier
Copy link
Member

@jasonkuhrt this just landed in most 1.6.1. Thanks again for raising the issue, and thanks @gcanti for the solution.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants