mirror of
https://github.com/nuxt/nuxt.git
synced 2025-02-16 13:48:13 +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 { FetchError } from 'ofetch'
|
||||||
import type { TypedInternalResponse, NitroFetchOptions, NitroFetchRequest } from 'nitropack'
|
import type { TypedInternalResponse, NitroFetchOptions, NitroFetchRequest, AvailableRouterMethod } from 'nitropack'
|
||||||
import type { Ref } from 'vue'
|
import type { Ref } from 'vue'
|
||||||
import { computed, unref, reactive } from 'vue'
|
import { computed, unref, reactive } from 'vue'
|
||||||
import { hash } from 'ohash'
|
import { hash } from 'ohash'
|
||||||
import type { AsyncDataOptions, _Transform, KeyOfRes, AsyncData, PickFrom } from './asyncData'
|
import type { AsyncDataOptions, _Transform, KeyOfRes, AsyncData, PickFrom } from './asyncData'
|
||||||
import { useAsyncData } 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>> = {
|
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]
|
[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<
|
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>,
|
||||||
R extends NitroFetchRequest = string & {}
|
R extends NitroFetchRequest = string & {},
|
||||||
> extends AsyncDataOptions<DataT, Transform, PickKeys>, ComputedFetchOptions<R> {
|
M extends AvailableRouterMethod<R> = AvailableRouterMethod<R>
|
||||||
|
> extends AsyncDataOptions<DataT, Transform, PickKeys>, ComputedFetchOptions<R, M> {
|
||||||
key?: string
|
key?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,23 +28,25 @@ export function useFetch<
|
|||||||
ResT = void,
|
ResT = void,
|
||||||
ErrorT = FetchError,
|
ErrorT = FetchError,
|
||||||
ReqT extends NitroFetchRequest = NitroFetchRequest,
|
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,
|
Transform extends (res: _ResT) => any = (res: _ResT) => _ResT,
|
||||||
PickKeys extends KeyOfRes<Transform> = KeyOfRes<Transform>
|
PickKeys extends KeyOfRes<Transform> = KeyOfRes<Transform>
|
||||||
> (
|
> (
|
||||||
request: Ref<ReqT> | ReqT | (() => ReqT),
|
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>
|
): AsyncData<PickFrom<ReturnType<Transform>, PickKeys>, ErrorT | null>
|
||||||
export function useFetch<
|
export function useFetch<
|
||||||
ResT = void,
|
ResT = void,
|
||||||
ErrorT = FetchError,
|
ErrorT = FetchError,
|
||||||
ReqT extends NitroFetchRequest = NitroFetchRequest,
|
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,
|
Transform extends (res: _ResT) => any = (res: _ResT) => _ResT,
|
||||||
PickKeys extends KeyOfRes<Transform> = KeyOfRes<Transform>
|
PickKeys extends KeyOfRes<Transform> = KeyOfRes<Transform>
|
||||||
> (
|
> (
|
||||||
request: Ref<ReqT> | ReqT | (() => ReqT),
|
request: Ref<ReqT> | ReqT | (() => ReqT),
|
||||||
arg1?: string | UseFetchOptions<_ResT, Transform, PickKeys, ReqT>,
|
arg1?: string | UseFetchOptions<_ResT, Transform, PickKeys, ReqT, Method>,
|
||||||
arg2?: string
|
arg2?: string
|
||||||
) {
|
) {
|
||||||
const [opts = {}, autoKey] = typeof arg1 === 'string' ? [{}, arg1] : [arg1, arg2]
|
const [opts = {}, autoKey] = typeof arg1 === 'string' ? [{}, arg1] : [arg1, arg2]
|
||||||
@ -109,23 +112,25 @@ export function useLazyFetch<
|
|||||||
ResT = void,
|
ResT = void,
|
||||||
ErrorT = FetchError,
|
ErrorT = FetchError,
|
||||||
ReqT extends NitroFetchRequest = NitroFetchRequest,
|
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,
|
Transform extends (res: _ResT) => any = (res: _ResT) => _ResT,
|
||||||
PickKeys extends KeyOfRes<Transform> = KeyOfRes<Transform>
|
PickKeys extends KeyOfRes<Transform> = KeyOfRes<Transform>
|
||||||
> (
|
> (
|
||||||
request: Ref<ReqT> | ReqT | (() => ReqT),
|
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>
|
): AsyncData<PickFrom<ReturnType<Transform>, PickKeys>, ErrorT | null>
|
||||||
export function useLazyFetch<
|
export function useLazyFetch<
|
||||||
ResT = void,
|
ResT = void,
|
||||||
ErrorT = FetchError,
|
ErrorT = FetchError,
|
||||||
ReqT extends NitroFetchRequest = NitroFetchRequest,
|
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,
|
Transform extends (res: _ResT) => any = (res: _ResT) => _ResT,
|
||||||
PickKeys extends KeyOfRes<Transform> = KeyOfRes<Transform>
|
PickKeys extends KeyOfRes<Transform> = KeyOfRes<Transform>
|
||||||
> (
|
> (
|
||||||
request: Ref<ReqT> | ReqT | (() => ReqT),
|
request: Ref<ReqT> | ReqT | (() => ReqT),
|
||||||
arg1?: string | Omit<UseFetchOptions<_ResT, Transform, PickKeys>, 'lazy'>,
|
arg1?: string | Omit<UseFetchOptions<_ResT, Transform, PickKeys, Method>, 'lazy'>,
|
||||||
arg2?: string
|
arg2?: string
|
||||||
) {
|
) {
|
||||||
const [opts, autoKey] = typeof arg1 === 'string' ? [{}, arg1] : [arg1, arg2]
|
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', () => {
|
it('generates types for routes', () => {
|
||||||
expectTypeOf($fetch('/api/hello')).toEqualTypeOf<Promise<string>>()
|
expectTypeOf($fetch('/api/hello')).toEqualTypeOf<Promise<string>>()
|
||||||
expectTypeOf($fetch('/api/hey')).toEqualTypeOf<Promise<{ foo: string, baz: 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/union')).toEqualTypeOf<Promise<{ type: 'a', foo: string } | { type: 'b', baz: string }>>()
|
||||||
expectTypeOf($fetch('/api/other')).toEqualTypeOf<Promise<unknown>>()
|
expectTypeOf($fetch('/api/other')).toEqualTypeOf<Promise<unknown>>()
|
||||||
expectTypeOf($fetch<TestResponse>('/test')).toEqualTypeOf<Promise<TestResponse>>()
|
expectTypeOf($fetch<TestResponse>('/test')).toEqualTypeOf<Promise<TestResponse>>()
|
||||||
@ -49,6 +52,10 @@ describe('API routes', () => {
|
|||||||
it('works with useFetch', () => {
|
it('works with useFetch', () => {
|
||||||
expectTypeOf(useFetch('/api/hello').data).toEqualTypeOf<Ref<string | null>>()
|
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').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/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').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>>()
|
expectTypeOf(useFetch('/api/union', { pick: ['type'] }).data).toEqualTypeOf<Ref<{ type: 'a' } | { type: 'b' } | null>>()
|
||||||
|
Loading…
Reference in New Issue
Block a user