From eb903bd66efb28a8e163b0d3bae091efd352f28d Mon Sep 17 00:00:00 2001 From: Alex Liu <39984251+Mini-ghost@users.noreply.github.com> Date: Sat, 30 Apr 2022 02:42:22 +0800 Subject: [PATCH] fix(nuxt3): improve error types for `useAsyncData` and `useFetch` (#4210) Co-authored-by: Daniel Roe --- docs/content/3.api/1.composables/use-fetch.md | 4 ++-- packages/nuxt/src/app/composables/asyncData.ts | 8 ++++---- packages/nuxt/src/app/composables/fetch.ts | 18 ++++++++++-------- test/fixtures/basic/types.ts | 15 +++++++++++++-- 4 files changed, 29 insertions(+), 16 deletions(-) diff --git a/docs/content/3.api/1.composables/use-fetch.md b/docs/content/3.api/1.composables/use-fetch.md index 426ca8a3c8..0fe4e7ba7d 100644 --- a/docs/content/3.api/1.composables/use-fetch.md +++ b/docs/content/3.api/1.composables/use-fetch.md @@ -6,7 +6,7 @@ This composable provides a convenient wrapper around [`useAsyncData`](/api/compo ```ts [Signature] function useFetch( - url: string, + url: string | Request, options?: UseFetchOptions ): Promise @@ -26,7 +26,7 @@ type DataT = { data: Ref pending: Ref refresh: () => Promise - error: Ref + error: Ref } ``` diff --git a/packages/nuxt/src/app/composables/asyncData.ts b/packages/nuxt/src/app/composables/asyncData.ts index d460df76c5..75161df87d 100644 --- a/packages/nuxt/src/app/composables/asyncData.ts +++ b/packages/nuxt/src/app/composables/asyncData.ts @@ -42,14 +42,14 @@ const getDefault = () => null export function useAsyncData< DataT, - DataE = any, + DataE = Error, Transform extends _Transform = _Transform, PickKeys extends KeyOfRes = KeyOfRes > ( key: string, handler: (ctx?: NuxtApp) => Promise, options: AsyncDataOptions = {} -): AsyncData, PickKeys>, DataE> { +): AsyncData, PickKeys>, DataE | null | true> { // Validate arguments if (typeof key !== 'string') { throw new TypeError('asyncData key must be a string') @@ -174,14 +174,14 @@ export function useAsyncData< export function useLazyAsyncData< DataT, - DataE = any, + DataE = Error, Transform extends _Transform = _Transform, PickKeys extends KeyOfRes = KeyOfRes > ( key: string, handler: (ctx?: NuxtApp) => Promise, options: Omit, 'lazy'> = {} -): AsyncData, PickKeys>, DataE> { +): AsyncData, PickKeys>, DataE | null | true> { return useAsyncData(key, handler, { ...options, lazy: true }) } diff --git a/packages/nuxt/src/app/composables/fetch.ts b/packages/nuxt/src/app/composables/fetch.ts index b994abc44a..dca5fba66a 100644 --- a/packages/nuxt/src/app/composables/fetch.ts +++ b/packages/nuxt/src/app/composables/fetch.ts @@ -11,15 +11,13 @@ export interface UseFetchOptions< DataT, Transform extends _Transform = _Transform, PickKeys extends KeyOfRes = KeyOfRes -> extends - AsyncDataOptions, - FetchOptions - { +> extends AsyncDataOptions, FetchOptions { key?: string - } +} export function useFetch< ResT = void, + ErrorT = Error, ReqT extends FetchRequest = FetchRequest, _ResT = ResT extends void ? FetchResult : ResT, Transform extends (res: _ResT) => any = (res: _ResT) => _ResT, @@ -53,8 +51,8 @@ export function useFetch< ] } - const asyncData = useAsyncData(key, () => { - return $fetch(_request.value, _fetchOptions) as Promise<_ResT> + const asyncData = useAsyncData<_ResT, ErrorT, Transform, PickKeys>(key, () => { + return $fetch(_request.value, _fetchOptions) }, _asyncDataOptions) return asyncData @@ -62,6 +60,7 @@ export function useFetch< export function useLazyFetch< ResT = void, + ErrorT = Error, ReqT extends string = string, _ResT = ResT extends void ? FetchResult : ResT, Transform extends (res: _ResT) => any = (res: _ResT) => _ResT, @@ -70,5 +69,8 @@ export function useLazyFetch< request: Ref | ReqT | (() => ReqT), opts: Omit, 'lazy'> = {} ) { - return useFetch(request, { ...opts, lazy: true }) + return useFetch(request, { + ...opts, + lazy: true + }) } diff --git a/test/fixtures/basic/types.ts b/test/fixtures/basic/types.ts index 35d73a2f3b..3522457920 100644 --- a/test/fixtures/basic/types.ts +++ b/test/fixtures/basic/types.ts @@ -23,14 +23,18 @@ describe('API routes', () => { expectTypeOf(useAsyncData('api-hey-with-pick', () => $fetch('/api/hey'), { pick: ['baz'] }).data).toMatchTypeOf>() expectTypeOf(useAsyncData('api-other', () => $fetch('/api/other')).data).toMatchTypeOf>() expectTypeOf(useAsyncData('api-generics', () => $fetch('/test')).data).toMatchTypeOf>() - expectTypeOf(useAsyncData('api-error-generics', () => $fetch('/test')).error).toMatchTypeOf>() + + expectTypeOf(useAsyncData('api-error-generics', () => $fetch('/error')).error).toMatchTypeOf>() + expectTypeOf(useAsyncData('api-error-generics', () => $fetch('/error')).error).toMatchTypeOf>() expectTypeOf(useLazyAsyncData('lazy-api-hello', () => $fetch('/api/hello')).data).toMatchTypeOf>() expectTypeOf(useLazyAsyncData('lazy-api-hey', () => $fetch('/api/hey')).data).toMatchTypeOf>() expectTypeOf(useLazyAsyncData('lazy-api-hey-with-pick', () => $fetch('/api/hey'), { pick: ['baz'] }).data).toMatchTypeOf>() expectTypeOf(useLazyAsyncData('lazy-api-other', () => $fetch('/api/other')).data).toMatchTypeOf>() expectTypeOf(useLazyAsyncData('lazy-api-generics', () => $fetch('/test')).data).toMatchTypeOf>() - expectTypeOf(useLazyAsyncData('lazy-error-generics', () => $fetch('/test')).error).toMatchTypeOf>() + + expectTypeOf(useLazyAsyncData('lazy-error-generics', () => $fetch('/error')).error).toMatchTypeOf>() + expectTypeOf(useLazyAsyncData('lazy-error-generics', () => $fetch('/error')).error).toMatchTypeOf>() }) it('works with useFetch', () => { @@ -39,12 +43,19 @@ describe('API routes', () => { expectTypeOf(useFetch('/api/hey', { pick: ['baz'] }).data).toMatchTypeOf>() expectTypeOf(useFetch('/api/other').data).toMatchTypeOf>() expectTypeOf(useFetch('/test').data).toMatchTypeOf>() + + expectTypeOf(useFetch('/error').error).toMatchTypeOf>() + expectTypeOf(useFetch('/error').error).toMatchTypeOf>() + expectTypeOf(useLazyFetch('/api/hello').data).toMatchTypeOf>() expectTypeOf(useLazyFetch('/api/hey').data).toMatchTypeOf>() expectTypeOf(useLazyFetch('/api/hey', { pick: ['baz'] }).data).toMatchTypeOf>() expectTypeOf(useLazyFetch('/api/other').data).toMatchTypeOf>() expectTypeOf(useLazyFetch('/api/other').data).toMatchTypeOf>() expectTypeOf(useLazyFetch('/test').data).toMatchTypeOf>() + + expectTypeOf(useLazyFetch('/error').error).toMatchTypeOf>() + expectTypeOf(useLazyFetch('/error').error).toMatchTypeOf>() }) })