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

Go-like syntax to handle errors #370

Open
1 task done
enkot opened this issue Mar 4, 2024 · 6 comments
Open
1 task done

Go-like syntax to handle errors #370

enkot opened this issue Mar 4, 2024 · 6 comments
Labels
discussion enhancement New feature or request

Comments

@enkot
Copy link

enkot commented Mar 4, 2024

Describe the feature

I suggest to add throw: boolean option so we can return the HTTP error instead of throwing it. This way users can get full type safety after implementation of Typed API definition.
Example:

const { data, error } = await $fetch('/api/v1', { throw: false })

or not throw by default:

const $api = $fetch.create<unknown, ApiDefinition>({
  baseURL: 'http://httpstat.us',
  throw: false
})

const { data, error } = await $api('/500')

error // -> error is typed here based on the ApiDefinition

data - 2xx response if OK, otherwise undefined
error - 5xx, 4xx response if not OK, otherwise undefined

Alternatives

Return array:

const [data, error] = $fetch('/api/v1', { throw: false })

Additional information

  • Would you be willing to help implement this feature?
@enkot enkot mentioned this issue Mar 4, 2024
1 task
@pi0 pi0 added enhancement New feature or request discussion labels Mar 5, 2024
@pi0
Copy link
Member

pi0 commented Mar 5, 2024

I like the idea. Only thinking it might be more suitable for $fetch.raw where we return full object (data body, headers and now possibly new headers). Combining two different return values for $fetch can increase the types complexity at very least but open to ideas.

@anuragkumar19
Copy link

I fully agree with @pi0.

@enkot, Generally APIs ErrorResponse schema is same for every routes. So, another way to achieve it would be we expose ErrorResponse interface which will be used by raw to override the response type with ErrorResponse if success is false. ErrorResponse can overwritten via .d.ts file.

Currently the work around will be to let your api return status_code:number or success:boolean & make response a union and use it with ignoreResponseError to get correct typing.

@johannschopplich
Copy link
Contributor

johannschopplich commented Mar 12, 2024

By the way, you could support both syntaxes in the same return object:

const { data, error } = $fetch('/api/v1', { throw: false })
// And:
const [data, error] = $fetch('/api/v1', { throw: false })

Implementation:

export function createIsomorphicDestructurable<
  T extends Record<string, unknown>,
  A extends readonly any[],
>(obj: T, arr: A): T & A {
  const clone = { ...obj }

  Object.defineProperty(clone, Symbol.iterator, {
    enumerable: false,
    value() {
      let index = 0
      return {
        next: () => ({
          value: arr[index++],
          done: index > arr.length,
        }),
      }
    },
  })

  return clone as T & A
}

This idea originated from @antfu.

@enkot
Copy link
Author

enkot commented Mar 12, 2024

Good point 👍
One more reference: https://vueuse.org/shared/makeDestructurable/#makedestructurable

@johannschopplich
Copy link
Contributor

johannschopplich commented Mar 12, 2024

@enkot Absolutely! It's the same implementation under the hood. The VueUse one also has IE11 support, probably because VueUse still supports Vue 2. :)

@enkot
Copy link
Author

enkot commented Mar 14, 2024

@enkot, Generally APIs ErrorResponse schema is same for every routes. So, another way to achieve it would be we expose ErrorResponse interface which will be used by raw to override the response type with ErrorResponse if success is false. ErrorResponse can overwritten via .d.ts file.

Agree, generally the same for all routes, but not 100%.
There are situations when, for example, the project uses gateways (aggregators) to different APIs and error response can be quite different.
An error response is just a different type of response (not 200), so why should it be treated differently in terms of types?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussion enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants