Skip to content

[Feature Request] Merge fields, Result.combine but for objects #651

@JesseGovindan

Description

@JesseGovindan

I think it would be useful to have a mergeFields method similar to Result.combine but which works with object fields

Usage:

const result = mergeFields({
  length: parseLength(lengthString), // returns Result<number, 'InvalidLengthString'>
  width: parseWidth(widthString), // returns Result<number, 'InvalidWidthString'>
})

// type of result is Result<{ length: number, width: number }, 'InvalidLengthString' | 'InvalidWidthString>

Possible implementation:

type ExtractOk<T extends Result<unknown, unknown>> = T extends Result<infer U, unknown> ? U : never
type ErrorUnion<U> = U[keyof U] extends Result<any, infer E> ? E : never;

export function mergeFields<R, E, U extends Record<string, Result<R, E>>>(results: U)
: Result<
  { [K in keyof U]: ExtractOk<U[K]> },
  ErrorUnion<U>
> {
  const unwrapped: Partial<Record<string, unknown>> = {};

  for (const key of Object.keys(results) as Array<keyof U>) {
    const r = results[key] as Result<unknown, ErrorUnion<U>>;
    if (r.isErr()) {
      return err(r.error);
    }
    unwrapped[key as string] = r.value;
  }

  return ok({
    ...(unwrapped as { [K in keyof U]: ExtractOk<U[K]> }),
  } as { [K in keyof U]: ExtractOk<U[K]> });
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions