Skip to content

Eliminate Need for both Union Type and Method Interface #2

@alexlafroscia

Description

@alexlafroscia

Right now, Result<T, E> is defined as a union between Ok<T> and Err<E>. This is so that properties like isOk and isErr can narrow a possible Result<T, E> into either an Ok<T> or an Err<E>, which can be useful, especially in cases where you have a situation like this:

function doSomething(input: Result<T, E>): Result<U, E> {
  if (input.isErr) {
    // No errors because we *know* that `input` is `Err<E>` which fits `Result<U, E>`
    return input;
  }

  // Otherwise do stuff
}

The problem is that there is nothing that ensures that Ok<T> and Err<E> have the same methods and there is no great place to document the methods from the perspective of calling them on a Result<T, E>; we can document them on Ok<T> and on Err<E> but that feels awkward, as the actual end-user is not usually working with one of those types. So, a second representation of Result is defined (ResultMethods) that is an interface that both of them implement. This helps with ensuring the methods are the same on both classes, and helps with type information in a user's editor, but is kind of awkward from a documentation standpoint; I'm having a real hard time getting the Deno docs page to link Result to ResultMethods so that people can actually navigate around the pages to find the method documentation.

Initially, this library was written differently; Result was an abstract base class that Ok and Err implemented, which felt a little nicer. However, this approach makes us lose the ability to use isOk and isErr to narrow the type from Result to Ok or Err:

Getters cannot narrow the type of the object they are called on
microsoft/TypeScript#43368

Methods have the same problem
microsoft/TypeScript#44212

So for now, we're left with both a Result<T, E> type and the ResultMethods interface.

If either of the above TypeScript issues get resolved, it would be a really nice ergonomic "win" for this library; it wouldn't change the way the library is used, but it would make the code easier to write and documentation easier to read.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions