Open Baloche opened 2 years ago
(nuxt 3.2)
The problem is related to AvailableRouterMethod<R>
type called by method
attribute in NitroFetchOptions
type definition from nitropack
package.
interface NitroFetchOptions<R extends NitroFetchRequest> extends FetchOptions {
method?: Uppercase<AvailableRouterMethod<R>> | AvailableRouterMethod<R>;
}
interface $Fetch<DefaultT = unknown, DefaultR extends NitroFetchRequest = NitroFetchRequest> {
<T = DefaultT, R extends NitroFetchRequest = DefaultR, O extends NitroFetchOptions<R> = NitroFetchOptions<R>>(request: R, opts?: O): Promise<TypedInternalResponse<R, T, ExtractedRouteMethod<R, O>>>;
raw<T = DefaultT, R extends NitroFetchRequest = DefaultR, O extends NitroFetchOptions<R> = NitroFetchOptions<R>>(request: R, opts?: O): Promise<FetchResponse<TypedInternalResponse<R, T, ExtractedRouteMethod<R, O>>>>;
create<T = DefaultT, R extends NitroFetchRequest = DefaultR>(defaults: FetchOptions): $Fetch<T, R>;
}
@pi0 can you take a look at this please? Can still reproduce in latest versions.
Still having this issue with:
import type { AvailableRouterMethod, NitroFetchRequest, NitroFetchOptions } from 'nitropack';
const $fetchApi = async <
ResT = void,
ReqT extends NitroFetchRequest = NitroFetchRequest,
Method extends AvailableRouterMethod<ReqT> = ResT extends void ? 'get' extends AvailableRouterMethod<ReqT> ? 'get' : AvailableRouterMethod<ReqT> : AvailableRouterMethod<ReqT>
>(
req: ReqT, opts?: NitroFetchOptions<ReqT>
)
Same here, problem still present:
const result:CasirestToken = await $fetch(settings.casirest.dev.endpoint + '/tokens', {
method: 'POST',
headers: {
'X-API-Key': settings.casirest.dev.apikey
},
body: creds
});
console.log(result);
/cc @danielroe
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
}
},
})
}
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,
});
}
having the same issue with that code:
const { data: cities, error: cityError } = await useAsyncData(
"posts",
() =>
// @ts-ignore
$fetch("/api/tool/data/city/", {
query: { departmentcode: departmentsSelect.value?.code },
}),
{
immediate: false,
watch: [departmentsSelect],
}
);
if (cityError.value) {
errorsHandler(cityError.value);
}
my error:
having the same issue with that code:
const { data: cities, error: cityError } = await useAsyncData( "posts", () => // @ts-ignore $fetch("/api/tool/data/city/", { query: { departmentcode: departmentsSelect.value?.code }, }), { immediate: false, watch: [departmentsSelect], } ); if (cityError.value) { errorsHandler(cityError.value); }
my error:
For this scenario, have you tried using useFetch
instead of useAsyncData
? You can pass query parameters too.
having the same issue with that code:
const { data: cities, error: cityError } = await useAsyncData( "posts", () => // @ts-ignore $fetch("/api/tool/data/city/", { query: { departmentcode: departmentsSelect.value?.code }, }), { immediate: false, watch: [departmentsSelect], } ); if (cityError.value) { errorsHandler(cityError.value); }
my error:
For this scenario, have you tried using
useFetch
instead ofuseAsyncData
? You can pass query parameters too.
yes I tried. Same error
@jervalles try this:
$fetch<unknown>("/api/tool/data/city/", {
query: { departmentcode: departmentsSelect.value?.code },
}),
Worked for me on Nuxt.
finally I wrap $fetch
on nuxt3
// types/index.d.ts
type FetchSchemaApi<DefaultApiResponse = unknown> = {
statusCode: number
data: DefaultApiResponse
}
declare module 'nitropack' {
interface $Fetch<DefaultT = unknown, DefaultR extends NitroFetchRequest = NitroFetchRequest> {
<T = DefaultT, R extends NitroFetchRequest = DefaultR, O extends NitroFetchOptions<R> = NitroFetchOptions<R>>(request: R, opts?: O): Promise<TypedInternalResponse<R, FetchSchemaApi<T>, ExtractedRouteMethod<R, O>>>;
raw<T = DefaultT, R extends NitroFetchRequest = DefaultR, O extends NitroFetchOptions<R> = NitroFetchOptions<R>>(request: R, opts?: O): Promise<FetchResponse<TypedInternalResponse<R, FetchSchemaApi<T>, ExtractedRouteMethod<R, O>>>>;
create<T = DefaultT, R extends NitroFetchRequest = DefaultR>(defaults: FetchOptions): $Fetch<FetchSchemaApi<T>, R>;
}
}
Im on Nuxt 3.9.1
and Vue 3.4.5
, I have this error when I use $fetch inside a function. (ignore the redeclare error, just for example)
const debounceFn = useDebounceFn(async () => {
results.value = await $fetch('/api/address/search', {
query: {
q: temp.value,
},
})
}, 750)
If I move $fetch outside, it doesn't complain
results.value = await $fetch('/api/address/search', {
query: {
q: temp.value,
},
})
Have the same problem when using $fetch
. Strangely I can't seem to reproduce it in a minimal reproduction, so it might have something to do with a large return type or the Nuxt project structure I have. This is a $fetch
GET call without any options, body or query.
Using Nuxt 3.11.2.
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
have same issue :(
workaround by @kenhyuwa work for me, but typecheck of return type not work anymore
Nuxt project info: 07:58:42
------------------------------
- Operating System: Windows_NT
- Node Version: v20.7.0
- Nuxt Version: 3.11.2
- CLI Version: 3.11.1
- Nitro Version: 2.9.6
- Package Manager: pnpm@8.15.6
- Builder: -
- User Config: typescript, devtools, app, build, modules, cron, pinia, experimental, auth
- Runtime Modules: @unocss/nuxt@0.58.9, @bg-dev/nuxt-naiveui@1.13.0, @nuxt/content@2.12.1, @pinia/nuxt@0.5.1, @vueuse/nuxt@10.9.0, @sidebase/nuxt-auth@0.7.1, nuxt-cron@1.5.1
This issue is still present. The workaround of providing a type to $fetch()
, like $fetch<myType>()
works, but of course this isn't ideal because we lose automatic type inference. This seems to point towards this automatic inference somehow tripping typescript.
I have tried again and again to reproduce this issue in a minimal app but it just doesn't show up there. It also only shows up for routes of a specific route folder. These routes do deal with numerous deep types inside them, returning large complex JSON data.
I am well aware that this is very difficult to fix if you can't make the error appear anywhere on your end, so it seems we're stuck providing the type hint ourselves for the time being.
this "Excessive stack" error comes and goes, but it's more likely to happen with default GET requests. Explicitly setting method: 'GET' seems to resolve the issue.
Steps to Reproduce:
/server/api
└── /something
├── index.get.ts
└── [id].put.ts
Make a default GET request using $fetch, then another request with a different method (e.g., PUT) with param:
const getSomething = $fetch('/api/something') // Likely to cause "Excessive stack" error
const putSomething = $fetch(/api/something/${id}, { method: 'PUT' })
How I got rid of it:
const getSomething = $fetch('/api/something', { method: 'GET' }) // Explicitly setting GET
const putSomething = $fetch(/api/something/${id}, { method: 'PUT' })
this "Excessive stack" error comes and goes, but it's more likely to happen with default GET requests. Explicitly setting method: 'GET' seems to resolve the issue.
Steps to Reproduce:
/server/api └── /something ├── index.get.ts └── [id].put.ts
Make a default GET request using $fetch, then another request with a different method (e.g., PUT) with param:
const getSomething = $fetch('/api/something') // Likely to cause "Excessive stack" error const putSomething = $fetch(/api/something/${id}, { method: 'PUT' })
How I got rid of it:
const getSomething = $fetch('/api/something', { method: 'GET' }) // Explicitly setting GET const putSomething = $fetch(/api/something/${id}, { method: 'PUT' })
For me still happens, despite I have method
defined.
Same for me, whether I try to wrap $fetch
or not, and whether I explicitly set the method
or not. It happens with Prisma so I suspect the type are indeed to complex to be inferred.
Same for me, whether I try to wrap
$fetch
or not, and whether I explicitly set themethod
or not. It happens with Prisma so I suspect the type are indeed to complex to be inferred.
Yes, it happens mostly because the types are complex to be inferred, or because there's lots of routes. This should be optimized somehow, is annoying always having that error everywhere.
Environment
Darwin
v16.15.1
3.0.0-rc.8
npm@8.11.0
vite
runtimeConfig
,css
,vite
,typescript
,modules
,unocss
@unocss/nuxt@^0.44.7
,@vueuse/nuxt@9.1.1
Build Modules:
-
Reproduction
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 anExcessive 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