nitro: TS error `Excessive stack depth comparing types` when trying to wrap `$fetch`

Environment


  • Operating System: Darwin
  • Node Version: v16.15.1
  • Nuxt Version: 3.0.0-rc.8
  • Package Manager: npm@8.11.0
  • Builder: vite
  • User Config: runtimeConfig, css, vite, typescript, modules, unocss
  • Runtime Modules: @unocss/nuxt@^0.44.7, @vueuse/nuxt@9.1.1
  • Build Modules: -

Reproduction

export const wrappedFetch: typeof $fetch = (request, opts?) => $fetch(request, opts)
wrappedFetch.raw = (request, opts?) => $fetch.raw(request, opts)

Describe the bug

In Nuxt 3.0.0-rc.8, when trying to wrap the $fetch method in a custom method with the same type signature (to set default options for example), typescript throw an Excessive stack depth comparing types error, forcing me to add // @ts-ignore on the line before.

This only happens for $fetch. useFetch can be wrapped without errors.

Is it normal ?

Additional context

No response

Logs

No response

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Reactions: 24
  • Comments: 16 (2 by maintainers)

Most upvoted comments

Finally found this workaround for $fetch, if anyone is interested :

import type {
  NitroFetchRequest,
} from "nitropack";

export function $api<
  T = unknown,
  R extends NitroFetchRequest = NitroFetchRequest
>(
  request: Parameters<typeof $fetch<T, R>>[0],
  opts?: Partial<Parameters<typeof $fetch<T, R>>[1]>
) {
  return $fetch<T, R>(request, {
    // add your custom options here
    ...opts,
  });
}

@pi0 can you take a look at this please? Can still reproduce in latest versions.

It is the same when trying to do with useFetch or useAsyncData. For those who stuck with useFetch, I managed it as this:

export const useFetchApi = <T>(
  ...[request, options]: Parameters<typeof useFetch<T>>
): ReturnType<typeof useFetch<T>> => {
  return useFetch<T>(request, {
    ...options,
    async onRequest({ options }) {
      const accessToken = await useAuthStore().getAccessToken()

      if (accessToken) {
        const headers = new Headers(options.headers)

        headers.set('Accept', 'application/json')
        headers.set('Authorization', `Bearer ${accessToken}`)

        options.headers = headers
      }
    },
  })
}

Yes, this issue is happening in big projects. The only workaround I found and using for now is to specify certain return type:

$fetch<{
  item: ISomeItemType
  ...
}>(...)

Using the latest Nuxt 3.11.2