neverthrow icon indicating copy to clipboard operation
neverthrow copied to clipboard

Improve `ResultAsync.map*` method types

Open rijenkii opened this issue 11 months ago • 3 comments

Those functions cannot receive callbacks that return type A | Promise<B>.

Reproduction for map (playground):

declare class ResultAsync<T, E> {
    map<A>(f: (t: T) => A | Promise<A>): ResultAsync<A, E>;
}

declare function mapper(x: string): number | Promise<string>;
declare const x: ResultAsync<string, never>;

const result = x.map(mapper);
// Argument of type '(x: string) => number | Promise<string>' is not assignable to parameter of type '(t: string) => string | Promise<string>'.
//   Type 'number | Promise<string>' is not assignable to type 'string | Promise<string>'.
//     Type 'number' is not assignable to type 'string | Promise<string>'.(2345)

A naïve solution that I came up with looks like this (playground):

declare class ResultAsync<T, E> {
  map<A>(f: (t: T) => A): ResultAsync<Awaited<A>, E>;
}

declare function mapper(x: string): number | Promise<string>;
declare const x: ResultAsync<string, never>;

const result = x.map(mapper);
//    ^? const result: ResultAsync<string | number, never>

This also applies to mapErr and potentially to then, but I have not tested that one.

rijenkii avatar Jan 17 '25 18:01 rijenkii