Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat(andFinally): add andFinally functionality #1

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

kishore03109
Copy link
Owner

@kishore03109 kishore03109 commented May 12, 2024

Description

Add 'finally' functionality to neverthrow. Overall leads to clearer typing with less verbose code. The mental model is similar to the native finally.

This PR attempts to solve 2 main issues. Consider the example below:

    const doesResourceExist = async (): Promise<true> => {
      const simulateError = () => Math.random() < 0.33
      if (simulateError()) {
        throw new Error('Unrecoverable error')
      }
      if (simulateError()) {
        throw new Error('404 Not found error')
      }
      return true
    }

    const safeFunction: ResultAsync<true, ResultAsync<boolean, unknown>> = ResultAsync.fromPromise(
      doesResourceExist(),
      (error) => error,
    ).mapErr((error) => {
      if (`${error}` === '404 Not found error') {
        return okAsync(false)
      }
      return errAsync(error)
    })

Notice the return type of the safeFunction is typed to an unintuitive type. Not sure if there was a convenient way for error recovery while mutating the Ok type. With andFinally, there is easier control over the Ok type during error recovery as such:

    const improvedSafeFunction: ResultAsync<boolean, unknown> = ResultAsync.fromPromise(
      doesResourceExist(),
      (error) => error,
    ).andFinally((error) => {
      if (`${error}` === 'Not found error') {
        return okAsync(false)
      }
      return errAsync(error)
    })

Additionally, this solves #<>. As documented in the issue, the below code becomes less verbose.

Before

    const doStuff: Result<string, never> = ok('start db connection')
      .andThen(() => {
        // do stuff that might return an err()
        const result: Result<string, string> = ok('do something')
        return result
      })
      .andThen(() => {
        return ok('close db connection')
      })
      .orElse(() => {
        return ok('close db connection')
      })

After

    const doStuff: Result<string, never> = ok("start db connection").andThen(() => {
      // do stuff that might return an err()
      const result: Result<string, string> = ok("do something")
      return result
    }).andFinally(() => {
      return ok("close db connection")
    })

Testing

Have added some minimal tests to capture correct behaviour.

@kishore03109 kishore03109 changed the title feat(andFinally): add addFinally functionality feat(andFinally): add andFinally functionality May 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
1 participant