mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-11 08:33:53 +00:00
feat(nuxt): infer useFetch
return based on the method (#18526)
This commit is contained in:
parent
526a78095a
commit
bae73c3650
@ -1,25 +1,26 @@
|
||||
import type { FetchError } from 'ofetch'
|
||||
import type { TypedInternalResponse, NitroFetchOptions, NitroFetchRequest } from 'nitropack'
|
||||
import type { TypedInternalResponse, NitroFetchOptions, NitroFetchRequest, AvailableRouterMethod } from 'nitropack'
|
||||
import type { Ref } from 'vue'
|
||||
import { computed, unref, reactive } from 'vue'
|
||||
import { hash } from 'ohash'
|
||||
import type { AsyncDataOptions, _Transform, KeyOfRes, AsyncData, PickFrom } from './asyncData'
|
||||
import { useAsyncData } from './asyncData'
|
||||
|
||||
export type FetchResult<ReqT extends NitroFetchRequest> = TypedInternalResponse<ReqT, unknown>
|
||||
export type FetchResult<ReqT extends NitroFetchRequest, M extends AvailableRouterMethod<ReqT>> = TypedInternalResponse<ReqT, unknown, M>
|
||||
|
||||
type ComputedOptions<T extends Record<string, any>> = {
|
||||
[K in keyof T]: T[K] extends Function ? T[K] : T[K] extends Record<string, any> ? ComputedOptions<T[K]> | Ref<T[K]> | T[K] : Ref<T[K]> | T[K]
|
||||
}
|
||||
|
||||
type ComputedFetchOptions<R extends NitroFetchRequest> = ComputedOptions<NitroFetchOptions<R>>
|
||||
type ComputedFetchOptions<R extends NitroFetchRequest, M extends AvailableRouterMethod<R>> = ComputedOptions<NitroFetchOptions<R, M>>
|
||||
|
||||
export interface UseFetchOptions<
|
||||
DataT,
|
||||
Transform extends _Transform<DataT, any> = _Transform<DataT, DataT>,
|
||||
PickKeys extends KeyOfRes<Transform> = KeyOfRes<Transform>,
|
||||
R extends NitroFetchRequest = string & {}
|
||||
> extends AsyncDataOptions<DataT, Transform, PickKeys>, ComputedFetchOptions<R> {
|
||||
R extends NitroFetchRequest = string & {},
|
||||
M extends AvailableRouterMethod<R> = AvailableRouterMethod<R>
|
||||
> extends AsyncDataOptions<DataT, Transform, PickKeys>, ComputedFetchOptions<R, M> {
|
||||
key?: string
|
||||
}
|
||||
|
||||
@ -27,23 +28,25 @@ export function useFetch<
|
||||
ResT = void,
|
||||
ErrorT = FetchError,
|
||||
ReqT extends NitroFetchRequest = NitroFetchRequest,
|
||||
_ResT = ResT extends void ? FetchResult<ReqT> : ResT,
|
||||
Method extends AvailableRouterMethod<ReqT> = 'get' extends AvailableRouterMethod<ReqT> ? 'get' : AvailableRouterMethod<ReqT>,
|
||||
_ResT = ResT extends void ? FetchResult<ReqT, Method> : ResT,
|
||||
Transform extends (res: _ResT) => any = (res: _ResT) => _ResT,
|
||||
PickKeys extends KeyOfRes<Transform> = KeyOfRes<Transform>
|
||||
> (
|
||||
request: Ref<ReqT> | ReqT | (() => ReqT),
|
||||
opts?: UseFetchOptions<_ResT, Transform, PickKeys, ReqT>
|
||||
opts?: UseFetchOptions<_ResT, Transform, PickKeys, ReqT, Method>
|
||||
): AsyncData<PickFrom<ReturnType<Transform>, PickKeys>, ErrorT | null>
|
||||
export function useFetch<
|
||||
ResT = void,
|
||||
ErrorT = FetchError,
|
||||
ReqT extends NitroFetchRequest = NitroFetchRequest,
|
||||
_ResT = ResT extends void ? FetchResult<ReqT> : ResT,
|
||||
Method extends AvailableRouterMethod<ReqT> = 'get' extends AvailableRouterMethod<ReqT> ? 'get' : AvailableRouterMethod<ReqT>,
|
||||
_ResT = ResT extends void ? FetchResult<ReqT, Method> : ResT,
|
||||
Transform extends (res: _ResT) => any = (res: _ResT) => _ResT,
|
||||
PickKeys extends KeyOfRes<Transform> = KeyOfRes<Transform>
|
||||
> (
|
||||
request: Ref<ReqT> | ReqT | (() => ReqT),
|
||||
arg1?: string | UseFetchOptions<_ResT, Transform, PickKeys, ReqT>,
|
||||
arg1?: string | UseFetchOptions<_ResT, Transform, PickKeys, ReqT, Method>,
|
||||
arg2?: string
|
||||
) {
|
||||
const [opts = {}, autoKey] = typeof arg1 === 'string' ? [{}, arg1] : [arg1, arg2]
|
||||
@ -109,23 +112,25 @@ export function useLazyFetch<
|
||||
ResT = void,
|
||||
ErrorT = FetchError,
|
||||
ReqT extends NitroFetchRequest = NitroFetchRequest,
|
||||
_ResT = ResT extends void ? FetchResult<ReqT> : ResT,
|
||||
Method extends AvailableRouterMethod<ReqT> = 'get' extends AvailableRouterMethod<ReqT> ? 'get' : AvailableRouterMethod<ReqT>,
|
||||
_ResT = ResT extends void ? FetchResult<ReqT, Method> : ResT,
|
||||
Transform extends (res: _ResT) => any = (res: _ResT) => _ResT,
|
||||
PickKeys extends KeyOfRes<Transform> = KeyOfRes<Transform>
|
||||
> (
|
||||
request: Ref<ReqT> | ReqT | (() => ReqT),
|
||||
opts?: Omit<UseFetchOptions<_ResT, Transform, PickKeys>, 'lazy'>
|
||||
opts?: Omit<UseFetchOptions<_ResT, Transform, PickKeys, Method>, 'lazy'>
|
||||
): AsyncData<PickFrom<ReturnType<Transform>, PickKeys>, ErrorT | null>
|
||||
export function useLazyFetch<
|
||||
ResT = void,
|
||||
ErrorT = FetchError,
|
||||
ReqT extends NitroFetchRequest = NitroFetchRequest,
|
||||
_ResT = ResT extends void ? FetchResult<ReqT> : ResT,
|
||||
Method extends AvailableRouterMethod<ReqT> = 'get' extends AvailableRouterMethod<ReqT> ? 'get' : AvailableRouterMethod<ReqT>,
|
||||
_ResT = ResT extends void ? FetchResult<ReqT, Method> : ResT,
|
||||
Transform extends (res: _ResT) => any = (res: _ResT) => _ResT,
|
||||
PickKeys extends KeyOfRes<Transform> = KeyOfRes<Transform>
|
||||
> (
|
||||
request: Ref<ReqT> | ReqT | (() => ReqT),
|
||||
arg1?: string | Omit<UseFetchOptions<_ResT, Transform, PickKeys>, 'lazy'>,
|
||||
arg1?: string | Omit<UseFetchOptions<_ResT, Transform, PickKeys, Method>, 'lazy'>,
|
||||
arg2?: string
|
||||
) {
|
||||
const [opts, autoKey] = typeof arg1 === 'string' ? [{}, arg1] : [arg1, arg2]
|
||||
|
7
test/fixtures/basic/types.ts
vendored
7
test/fixtures/basic/types.ts
vendored
@ -17,6 +17,9 @@ describe('API routes', () => {
|
||||
it('generates types for routes', () => {
|
||||
expectTypeOf($fetch('/api/hello')).toEqualTypeOf<Promise<string>>()
|
||||
expectTypeOf($fetch('/api/hey')).toEqualTypeOf<Promise<{ foo: string, baz: string }>>()
|
||||
expectTypeOf($fetch('/api/hey', { method: 'get' })).toEqualTypeOf<Promise<{ foo: string, baz: string }>>()
|
||||
// @ts-expect-error not a valid method
|
||||
expectTypeOf($fetch('/api/hey', { method: 'patch ' })).toEqualTypeOf<Promise<{ foo: string, baz: string }>>()
|
||||
expectTypeOf($fetch('/api/union')).toEqualTypeOf<Promise<{ type: 'a', foo: string } | { type: 'b', baz: string }>>()
|
||||
expectTypeOf($fetch('/api/other')).toEqualTypeOf<Promise<unknown>>()
|
||||
expectTypeOf($fetch<TestResponse>('/test')).toEqualTypeOf<Promise<TestResponse>>()
|
||||
@ -49,6 +52,10 @@ describe('API routes', () => {
|
||||
it('works with useFetch', () => {
|
||||
expectTypeOf(useFetch('/api/hello').data).toEqualTypeOf<Ref<string | null>>()
|
||||
expectTypeOf(useFetch('/api/hey').data).toEqualTypeOf<Ref<{ foo: string, baz: string } | null>>()
|
||||
expectTypeOf(useFetch('/api/hey', { method: 'GET' }).data).toEqualTypeOf<Ref<{ foo: string, baz: string } | null>>()
|
||||
expectTypeOf(useFetch('/api/hey', { method: 'get' }).data).toEqualTypeOf<Ref<{ foo: string, baz: string } | null>>()
|
||||
// @ts-expect-error not a valid method
|
||||
useFetch('/api/hey', { method: 'PATCH' })
|
||||
expectTypeOf(useFetch('/api/hey', { pick: ['baz'] }).data).toEqualTypeOf<Ref<{ baz: string } | null>>()
|
||||
expectTypeOf(useFetch('/api/union').data).toEqualTypeOf<Ref<{ type: 'a', foo: string } | { type: 'b', baz: string } | null>>()
|
||||
expectTypeOf(useFetch('/api/union', { pick: ['type'] }).data).toEqualTypeOf<Ref<{ type: 'a' } | { type: 'b' } | null>>()
|
||||
|
Loading…
Reference in New Issue
Block a user