mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-22 05:35:13 +00:00
fix(nuxt3): improve error types for useAsyncData
and useFetch
(#4210)
Co-authored-by: Daniel Roe <daniel@roe.dev>
This commit is contained in:
parent
2a3fbb4c24
commit
eb903bd66e
@ -6,7 +6,7 @@ This composable provides a convenient wrapper around [`useAsyncData`](/api/compo
|
|||||||
|
|
||||||
```ts [Signature]
|
```ts [Signature]
|
||||||
function useFetch(
|
function useFetch(
|
||||||
url: string,
|
url: string | Request,
|
||||||
options?: UseFetchOptions
|
options?: UseFetchOptions
|
||||||
): Promise<DataT>
|
): Promise<DataT>
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ type DataT = {
|
|||||||
data: Ref<DataT>
|
data: Ref<DataT>
|
||||||
pending: Ref<boolean>
|
pending: Ref<boolean>
|
||||||
refresh: () => Promise<void>
|
refresh: () => Promise<void>
|
||||||
error: Ref<any>
|
error: Ref<Error | boolean>
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -42,14 +42,14 @@ const getDefault = () => null
|
|||||||
|
|
||||||
export function useAsyncData<
|
export function useAsyncData<
|
||||||
DataT,
|
DataT,
|
||||||
DataE = any,
|
DataE = Error,
|
||||||
Transform extends _Transform<DataT> = _Transform<DataT, DataT>,
|
Transform extends _Transform<DataT> = _Transform<DataT, DataT>,
|
||||||
PickKeys extends KeyOfRes<Transform> = KeyOfRes<Transform>
|
PickKeys extends KeyOfRes<Transform> = KeyOfRes<Transform>
|
||||||
> (
|
> (
|
||||||
key: string,
|
key: string,
|
||||||
handler: (ctx?: NuxtApp) => Promise<DataT>,
|
handler: (ctx?: NuxtApp) => Promise<DataT>,
|
||||||
options: AsyncDataOptions<DataT, Transform, PickKeys> = {}
|
options: AsyncDataOptions<DataT, Transform, PickKeys> = {}
|
||||||
): AsyncData<PickFrom<ReturnType<Transform>, PickKeys>, DataE> {
|
): AsyncData<PickFrom<ReturnType<Transform>, PickKeys>, DataE | null | true> {
|
||||||
// Validate arguments
|
// Validate arguments
|
||||||
if (typeof key !== 'string') {
|
if (typeof key !== 'string') {
|
||||||
throw new TypeError('asyncData key must be a string')
|
throw new TypeError('asyncData key must be a string')
|
||||||
@ -174,14 +174,14 @@ export function useAsyncData<
|
|||||||
|
|
||||||
export function useLazyAsyncData<
|
export function useLazyAsyncData<
|
||||||
DataT,
|
DataT,
|
||||||
DataE = any,
|
DataE = Error,
|
||||||
Transform extends _Transform<DataT> = _Transform<DataT, DataT>,
|
Transform extends _Transform<DataT> = _Transform<DataT, DataT>,
|
||||||
PickKeys extends KeyOfRes<Transform> = KeyOfRes<Transform>
|
PickKeys extends KeyOfRes<Transform> = KeyOfRes<Transform>
|
||||||
> (
|
> (
|
||||||
key: string,
|
key: string,
|
||||||
handler: (ctx?: NuxtApp) => Promise<DataT>,
|
handler: (ctx?: NuxtApp) => Promise<DataT>,
|
||||||
options: Omit<AsyncDataOptions<DataT, Transform, PickKeys>, 'lazy'> = {}
|
options: Omit<AsyncDataOptions<DataT, Transform, PickKeys>, 'lazy'> = {}
|
||||||
): AsyncData<PickFrom<ReturnType<Transform>, PickKeys>, DataE> {
|
): AsyncData<PickFrom<ReturnType<Transform>, PickKeys>, DataE | null | true> {
|
||||||
return useAsyncData(key, handler, { ...options, lazy: true })
|
return useAsyncData(key, handler, { ...options, lazy: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,15 +11,13 @@ export interface UseFetchOptions<
|
|||||||
DataT,
|
DataT,
|
||||||
Transform extends _Transform<DataT, any> = _Transform<DataT, DataT>,
|
Transform extends _Transform<DataT, any> = _Transform<DataT, DataT>,
|
||||||
PickKeys extends KeyOfRes<Transform> = KeyOfRes<Transform>
|
PickKeys extends KeyOfRes<Transform> = KeyOfRes<Transform>
|
||||||
> extends
|
> extends AsyncDataOptions<DataT, Transform, PickKeys>, FetchOptions {
|
||||||
AsyncDataOptions<DataT, Transform, PickKeys>,
|
|
||||||
FetchOptions
|
|
||||||
{
|
|
||||||
key?: string
|
key?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useFetch<
|
export function useFetch<
|
||||||
ResT = void,
|
ResT = void,
|
||||||
|
ErrorT = Error,
|
||||||
ReqT extends FetchRequest = FetchRequest,
|
ReqT extends FetchRequest = FetchRequest,
|
||||||
_ResT = ResT extends void ? FetchResult<ReqT> : ResT,
|
_ResT = ResT extends void ? FetchResult<ReqT> : ResT,
|
||||||
Transform extends (res: _ResT) => any = (res: _ResT) => _ResT,
|
Transform extends (res: _ResT) => any = (res: _ResT) => _ResT,
|
||||||
@ -53,8 +51,8 @@ export function useFetch<
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
const asyncData = useAsyncData(key, () => {
|
const asyncData = useAsyncData<_ResT, ErrorT, Transform, PickKeys>(key, () => {
|
||||||
return $fetch(_request.value, _fetchOptions) as Promise<_ResT>
|
return $fetch(_request.value, _fetchOptions)
|
||||||
}, _asyncDataOptions)
|
}, _asyncDataOptions)
|
||||||
|
|
||||||
return asyncData
|
return asyncData
|
||||||
@ -62,6 +60,7 @@ export function useFetch<
|
|||||||
|
|
||||||
export function useLazyFetch<
|
export function useLazyFetch<
|
||||||
ResT = void,
|
ResT = void,
|
||||||
|
ErrorT = Error,
|
||||||
ReqT extends string = string,
|
ReqT extends string = string,
|
||||||
_ResT = ResT extends void ? FetchResult<ReqT> : ResT,
|
_ResT = ResT extends void ? FetchResult<ReqT> : ResT,
|
||||||
Transform extends (res: _ResT) => any = (res: _ResT) => _ResT,
|
Transform extends (res: _ResT) => any = (res: _ResT) => _ResT,
|
||||||
@ -70,5 +69,8 @@ export function useLazyFetch<
|
|||||||
request: Ref<ReqT> | ReqT | (() => ReqT),
|
request: Ref<ReqT> | ReqT | (() => ReqT),
|
||||||
opts: Omit<UseFetchOptions<_ResT, Transform, PickKeys>, 'lazy'> = {}
|
opts: Omit<UseFetchOptions<_ResT, Transform, PickKeys>, 'lazy'> = {}
|
||||||
) {
|
) {
|
||||||
return useFetch(request, { ...opts, lazy: true })
|
return useFetch<ResT, ErrorT, ReqT, _ResT, Transform, PickKeys>(request, {
|
||||||
|
...opts,
|
||||||
|
lazy: true
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
15
test/fixtures/basic/types.ts
vendored
15
test/fixtures/basic/types.ts
vendored
@ -23,14 +23,18 @@ describe('API routes', () => {
|
|||||||
expectTypeOf(useAsyncData('api-hey-with-pick', () => $fetch('/api/hey'), { pick: ['baz'] }).data).toMatchTypeOf<Ref<{ baz: string }>>()
|
expectTypeOf(useAsyncData('api-hey-with-pick', () => $fetch('/api/hey'), { pick: ['baz'] }).data).toMatchTypeOf<Ref<{ baz: string }>>()
|
||||||
expectTypeOf(useAsyncData('api-other', () => $fetch('/api/other')).data).toMatchTypeOf<Ref<unknown>>()
|
expectTypeOf(useAsyncData('api-other', () => $fetch('/api/other')).data).toMatchTypeOf<Ref<unknown>>()
|
||||||
expectTypeOf(useAsyncData<TestResponse>('api-generics', () => $fetch('/test')).data).toMatchTypeOf<Ref<TestResponse>>()
|
expectTypeOf(useAsyncData<TestResponse>('api-generics', () => $fetch('/test')).data).toMatchTypeOf<Ref<TestResponse>>()
|
||||||
expectTypeOf(useAsyncData<any, string>('api-error-generics', () => $fetch('/test')).error).toMatchTypeOf<Ref<string>>()
|
|
||||||
|
expectTypeOf(useAsyncData('api-error-generics', () => $fetch('/error')).error).toMatchTypeOf<Ref<Error | true | null>>()
|
||||||
|
expectTypeOf(useAsyncData<any, string>('api-error-generics', () => $fetch('/error')).error).toMatchTypeOf<Ref<string | true | null>>()
|
||||||
|
|
||||||
expectTypeOf(useLazyAsyncData('lazy-api-hello', () => $fetch('/api/hello')).data).toMatchTypeOf<Ref<string>>()
|
expectTypeOf(useLazyAsyncData('lazy-api-hello', () => $fetch('/api/hello')).data).toMatchTypeOf<Ref<string>>()
|
||||||
expectTypeOf(useLazyAsyncData('lazy-api-hey', () => $fetch('/api/hey')).data).toMatchTypeOf<Ref<{ foo:string, baz: string }>>()
|
expectTypeOf(useLazyAsyncData('lazy-api-hey', () => $fetch('/api/hey')).data).toMatchTypeOf<Ref<{ foo:string, baz: string }>>()
|
||||||
expectTypeOf(useLazyAsyncData('lazy-api-hey-with-pick', () => $fetch('/api/hey'), { pick: ['baz'] }).data).toMatchTypeOf<Ref<{ baz: string }>>()
|
expectTypeOf(useLazyAsyncData('lazy-api-hey-with-pick', () => $fetch('/api/hey'), { pick: ['baz'] }).data).toMatchTypeOf<Ref<{ baz: string }>>()
|
||||||
expectTypeOf(useLazyAsyncData('lazy-api-other', () => $fetch('/api/other')).data).toMatchTypeOf<Ref<unknown>>()
|
expectTypeOf(useLazyAsyncData('lazy-api-other', () => $fetch('/api/other')).data).toMatchTypeOf<Ref<unknown>>()
|
||||||
expectTypeOf(useLazyAsyncData<TestResponse>('lazy-api-generics', () => $fetch('/test')).data).toMatchTypeOf<Ref<TestResponse>>()
|
expectTypeOf(useLazyAsyncData<TestResponse>('lazy-api-generics', () => $fetch('/test')).data).toMatchTypeOf<Ref<TestResponse>>()
|
||||||
expectTypeOf(useLazyAsyncData<any, string>('lazy-error-generics', () => $fetch('/test')).error).toMatchTypeOf<Ref<string>>()
|
|
||||||
|
expectTypeOf(useLazyAsyncData('lazy-error-generics', () => $fetch('/error')).error).toMatchTypeOf<Ref<Error | true | null>>()
|
||||||
|
expectTypeOf(useLazyAsyncData<any, string>('lazy-error-generics', () => $fetch('/error')).error).toMatchTypeOf<Ref<string | true | null>>()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('works with useFetch', () => {
|
it('works with useFetch', () => {
|
||||||
@ -39,12 +43,19 @@ describe('API routes', () => {
|
|||||||
expectTypeOf(useFetch('/api/hey', { pick: ['baz'] }).data).toMatchTypeOf<Ref<{ baz: string }>>()
|
expectTypeOf(useFetch('/api/hey', { pick: ['baz'] }).data).toMatchTypeOf<Ref<{ baz: string }>>()
|
||||||
expectTypeOf(useFetch('/api/other').data).toMatchTypeOf<Ref<unknown>>()
|
expectTypeOf(useFetch('/api/other').data).toMatchTypeOf<Ref<unknown>>()
|
||||||
expectTypeOf(useFetch<TestResponse>('/test').data).toMatchTypeOf<Ref<TestResponse>>()
|
expectTypeOf(useFetch<TestResponse>('/test').data).toMatchTypeOf<Ref<TestResponse>>()
|
||||||
|
|
||||||
|
expectTypeOf(useFetch('/error').error).toMatchTypeOf<Ref<Error | null | true>>()
|
||||||
|
expectTypeOf(useFetch<any, string>('/error').error).toMatchTypeOf<Ref<string | null | true>>()
|
||||||
|
|
||||||
expectTypeOf(useLazyFetch('/api/hello').data).toMatchTypeOf<Ref<string>>()
|
expectTypeOf(useLazyFetch('/api/hello').data).toMatchTypeOf<Ref<string>>()
|
||||||
expectTypeOf(useLazyFetch('/api/hey').data).toMatchTypeOf<Ref<{ foo:string, baz: string }>>()
|
expectTypeOf(useLazyFetch('/api/hey').data).toMatchTypeOf<Ref<{ foo:string, baz: string }>>()
|
||||||
expectTypeOf(useLazyFetch('/api/hey', { pick: ['baz'] }).data).toMatchTypeOf<Ref<{ baz: string }>>()
|
expectTypeOf(useLazyFetch('/api/hey', { pick: ['baz'] }).data).toMatchTypeOf<Ref<{ baz: string }>>()
|
||||||
expectTypeOf(useLazyFetch('/api/other').data).toMatchTypeOf<Ref<unknown>>()
|
expectTypeOf(useLazyFetch('/api/other').data).toMatchTypeOf<Ref<unknown>>()
|
||||||
expectTypeOf(useLazyFetch('/api/other').data).toMatchTypeOf<Ref<unknown>>()
|
expectTypeOf(useLazyFetch('/api/other').data).toMatchTypeOf<Ref<unknown>>()
|
||||||
expectTypeOf(useLazyFetch<TestResponse>('/test').data).toMatchTypeOf<Ref<TestResponse>>()
|
expectTypeOf(useLazyFetch<TestResponse>('/test').data).toMatchTypeOf<Ref<TestResponse>>()
|
||||||
|
|
||||||
|
expectTypeOf(useLazyFetch('/error').error).toMatchTypeOf<Ref<Error | null | true>>()
|
||||||
|
expectTypeOf(useLazyFetch<any, string>('/error').error).toMatchTypeOf<Ref<string | null | true>>()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user