Skip to content

Promise type should separate failure and success types separately #1232

@Gozala

Description

@Gozala

Current type definition of Promise takes single polymorphic parameter R that seems to represent type of the value it will be successfully fulfilled with:

https://github.com/facebook/flow/blob/master/lib/core.js#L422

Unfortunately this mean error case is untyped:
https://github.com/facebook/flow/blob/master/lib/core.js#L423

Furthermore onFulfill handler can return rejected promise and there for make result of .then rejected promise.

I run into this issue with a code like:

class Future <error, value> {
  type: "Async";
  promise: () => Promise<value>;
  constructor(promise:() => Promise<value>) {
    super()
    this.type = "Async"
    this.promise = promise
  }
  await(resume:(task:Task<error, value>) => void):void {
    this
      .promise()
      .then(Task.succeed, fail)
      .then(Task.resume)
  }
}

Problem is I can no longer restrict errors that task can fail with. Which is why I'd like to propose altering a type definition for promises as follows:

// Bottomless type that can't be instantiated
type Never = Never

declare class Promise<R, X> {
    constructor(callback: (
      resolve: (result: R | Promise<R, X>) => void,
      reject:  (error: X) => void
    ) => mixed): void;

    then<U, Y>(
      onFulfill?: (value: R) => U | Promise<U, Y>,
      onReject?: (error: X) => U | Promise<U, Y>
    ): Promise<U, Y>;

    catch<U, Y>(
      onReject?: (error: X) => U | Promise<U, Y>
    ): Promise<U, Y>;

    static resolve<T>(object?: Promise<T> | T): Promise<T, Never>;
    static reject<Y>(error?: X): Promise<Never, Y>;
    static all<T, Y, Elem: Promise<T, Y> | T>(promises: Array<Elem>): Promise<Array<T>, Y>;
    static race<T, Y, Elem: Promise<T, Y> | T>(promises: Array<Elem>): Promise<T, Y>;

    // Non-standard APIs common in some libraries

    done(
      onFulfill?: (value: R) => mixed,
      onReject?: (error: X) => mixed
    ): void;

    static cast<T>(object?: T): Promise<T, Never>;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions