From 7046930a677f4c987afaee5a0165841b0e0a517f Mon Sep 17 00:00:00 2001 From: Maik Kowol Date: Sun, 23 Jul 2023 10:24:54 +0200 Subject: [PATCH] fix(nuxt): add overloads for `asyncData` generic + default (#22258) --- .../nuxt/src/app/composables/asyncData.ts | 43 +++++++++++++++++++ packages/nuxt/src/app/composables/fetch.ts | 26 +++++++++++ test/fixtures/basic-types/types.ts | 27 ++++++++++++ 3 files changed, 96 insertions(+) diff --git a/packages/nuxt/src/app/composables/asyncData.ts b/packages/nuxt/src/app/composables/asyncData.ts index 9cfad40dd4..817c7d0432 100644 --- a/packages/nuxt/src/app/composables/asyncData.ts +++ b/packages/nuxt/src/app/composables/asyncData.ts @@ -78,6 +78,16 @@ export function useAsyncData< handler: (ctx?: NuxtApp) => Promise, options?: AsyncDataOptions ): AsyncData | DefaultT, DataE | null> +export function useAsyncData< + ResT, + DataE = Error, + DataT = ResT, + PickKeys extends KeysOf = KeysOf, + DefaultT = DataT, +> ( + handler: (ctx?: NuxtApp) => Promise, + options?: AsyncDataOptions +): AsyncData | DefaultT, DataE | null> export function useAsyncData< ResT, DataE = Error, @@ -89,6 +99,17 @@ export function useAsyncData< handler: (ctx?: NuxtApp) => Promise, options?: AsyncDataOptions ): AsyncData | DefaultT, DataE | null> +export function useAsyncData< + ResT, + DataE = Error, + DataT = ResT, + PickKeys extends KeysOf = KeysOf, + DefaultT = DataT, +> ( + key: string, + handler: (ctx?: NuxtApp) => Promise, + options?: AsyncDataOptions +): AsyncData | DefaultT, DataE | null> export function useAsyncData< ResT, DataE = Error, @@ -267,6 +288,16 @@ export function useLazyAsyncData< handler: (ctx?: NuxtApp) => Promise, options?: Omit, 'lazy'> ): AsyncData | DefaultT, DataE | null> +export function useLazyAsyncData< + ResT, + DataE = Error, + DataT = ResT, + PickKeys extends KeysOf = KeysOf, + DefaultT = DataT, +> ( + handler: (ctx?: NuxtApp) => Promise, + options?: Omit, 'lazy'> +): AsyncData | DefaultT, DataE | null> export function useLazyAsyncData< ResT, DataE = Error, @@ -278,6 +309,18 @@ export function useLazyAsyncData< handler: (ctx?: NuxtApp) => Promise, options?: Omit, 'lazy'> ): AsyncData | DefaultT, DataE | null> +export function useLazyAsyncData< + ResT, + DataE = Error, + DataT = ResT, + PickKeys extends KeysOf = KeysOf, + DefaultT = DataT, +> ( + key: string, + handler: (ctx?: NuxtApp) => Promise, + options?: Omit, 'lazy'> +): AsyncData | DefaultT, DataE | null> + export function useLazyAsyncData< ResT, DataE = Error, diff --git a/packages/nuxt/src/app/composables/fetch.ts b/packages/nuxt/src/app/composables/fetch.ts index d838346d2c..11ea5aeffb 100644 --- a/packages/nuxt/src/app/composables/fetch.ts +++ b/packages/nuxt/src/app/composables/fetch.ts @@ -41,6 +41,19 @@ export function useFetch< request: Ref | ReqT | (() => ReqT), opts?: UseFetchOptions<_ResT, DataT, PickKeys, DefaultT, ReqT, Method> ): AsyncData | DefaultT, ErrorT | null> +export function useFetch< + ResT = void, + ErrorT = FetchError, + ReqT extends NitroFetchRequest = NitroFetchRequest, + Method extends AvailableRouterMethod = ResT extends void ? 'get' extends AvailableRouterMethod ? 'get' : AvailableRouterMethod : AvailableRouterMethod, + _ResT = ResT extends void ? FetchResult : ResT, + DataT = _ResT, + PickKeys extends KeysOf = KeysOf, + DefaultT = DataT, +> ( + request: Ref | ReqT | (() => ReqT), + opts?: UseFetchOptions<_ResT, DataT, PickKeys, DefaultT, ReqT, Method> +): AsyncData | DefaultT, ErrorT | null> export function useFetch< ResT = void, ErrorT = FetchError, @@ -136,6 +149,19 @@ export function useLazyFetch< request: Ref | ReqT | (() => ReqT), opts?: Omit, 'lazy'> ): AsyncData | DefaultT, ErrorT | null> +export function useLazyFetch< + ResT = void, + ErrorT = FetchError, + ReqT extends NitroFetchRequest = NitroFetchRequest, + Method extends AvailableRouterMethod = ResT extends void ? 'get' extends AvailableRouterMethod ? 'get' : AvailableRouterMethod : AvailableRouterMethod, + _ResT = ResT extends void ? FetchResult : ResT, + DataT = _ResT, + PickKeys extends KeysOf = KeysOf, + DefaultT = DataT, +> ( + request: Ref | ReqT | (() => ReqT), + opts?: Omit, 'lazy'> +): AsyncData | DefaultT, ErrorT | null> export function useLazyFetch< ResT = void, ErrorT = FetchError, diff --git a/test/fixtures/basic-types/types.ts b/test/fixtures/basic-types/types.ts index e28585cedc..74d9868a90 100644 --- a/test/fixtures/basic-types/types.ts +++ b/test/fixtures/basic-types/types.ts @@ -309,6 +309,33 @@ describe('composables', () => { expectTypeOf(useFetch('/test', { default: () => 500 }).data).toEqualTypeOf>() }) + it('correct types when using ResT type-assertion with default function', () => { + // @ts-expect-error default type should match generic type + useFetch('/test', { default: () => 0 }) + // @ts-expect-error default type should match generic type + useLazyFetch('/test', { default: () => 0 }) + // @ts-expect-error default type should match generic type + useAsyncData(() => $fetch('/test'), { default: () => 0 }) + // @ts-expect-error default type should match generic type + useLazyAsyncData(() => $fetch('/test'), { default: () => 0 }) + + expectTypeOf(useFetch('/test', { default: () => 'test' }).data).toEqualTypeOf>() + expectTypeOf(useLazyFetch('/test', { default: () => 'test' }).data).toEqualTypeOf>() + expectTypeOf(useAsyncData(() => $fetch('/test'), { default: () => 'test' }).data).toEqualTypeOf>() + expectTypeOf(useLazyAsyncData(() => $fetch('/test'), { default: () => 'test' }).data).toEqualTypeOf>() + + // transform must match the explicit generic because of typescript limiations microsoft/TypeScript#14400 + expectTypeOf(useFetch('/test', { transform: () => 'transformed' }).data).toEqualTypeOf>() + expectTypeOf(useLazyFetch('/test', { transform: () => 'transformed' }).data).toEqualTypeOf>() + expectTypeOf(useAsyncData(() => $fetch('/test'), { transform: () => 'transformed' }).data).toEqualTypeOf>() + expectTypeOf(useLazyAsyncData(() => $fetch('/test'), { transform: () => 'transformed' }).data).toEqualTypeOf>() + + expectTypeOf(useFetch('/test', { default: () => 'test', transform: () => 'transformed' }).data).toEqualTypeOf>() + expectTypeOf(useLazyFetch('/test', { default: () => 'test', transform: () => 'transformed' }).data).toEqualTypeOf>() + expectTypeOf(useAsyncData(() => $fetch('/test'), { default: () => 'test', transform: () => 'transformed' }).data).toEqualTypeOf>() + expectTypeOf(useLazyAsyncData(() => $fetch('/test'), { default: () => 'test', transform: () => 'transformed' }).data).toEqualTypeOf>() + }) + it('infer request url string literal from server/api routes', () => { // request can accept dynamic string type const dynamicStringUrl = 'https://example.com/api'