From 98a02744bdac854757bfacfbf108029d31a891db Mon Sep 17 00:00:00 2001 From: Han Date: Tue, 9 Apr 2024 01:38:40 +0800 Subject: [PATCH] fix(nuxt): prevent `getCachedData` from shaping type of `useAsyncData` (#25946) --- packages/nuxt/src/app/composables/asyncData.ts | 4 +++- test/fixtures/basic-types/types.ts | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/nuxt/src/app/composables/asyncData.ts b/packages/nuxt/src/app/composables/asyncData.ts index d9fd2ae1d5..bbce72906a 100644 --- a/packages/nuxt/src/app/composables/asyncData.ts +++ b/packages/nuxt/src/app/composables/asyncData.ts @@ -36,6 +36,8 @@ export type KeyOfRes = KeysOf | object)[] +export type NoInfer = [T][T extends any ? 0 : never] + export interface AsyncDataOptions< ResT, DataT = ResT, @@ -61,7 +63,7 @@ export interface AsyncDataOptions< * A `null` or `undefined` return value will trigger a fetch. * Default is `key => nuxt.isHydrating ? nuxt.payload.data[key] : nuxt.static.data[key]` which only caches data when payloadExtraction is enabled. */ - getCachedData?: (key: string, nuxtApp: NuxtApp) => DataT + getCachedData?: (key: string, nuxtApp: NuxtApp) => NoInfer /** * A function that can be used to alter handler function result after resolving. * Do not use it along with the `pick` option. diff --git a/test/fixtures/basic-types/types.ts b/test/fixtures/basic-types/types.ts index 0c450541b4..f20bf6d556 100644 --- a/test/fixtures/basic-types/types.ts +++ b/test/fixtures/basic-types/types.ts @@ -512,6 +512,20 @@ describe('composables', () => { expectTypeOf(notTypedData.value!.content).toEqualTypeOf() expectTypeOf(notTypedData.value!.untypedKey).toEqualTypeOf() }) + + it('correctly types returns when using with getCachedData', () => { + expectTypeOf(useAsyncData('test', () => Promise.resolve({ foo: 1 }), { + getCachedData: key => useNuxtApp().payload.data[key], + }).data).toEqualTypeOf>() + useAsyncData('test', () => Promise.resolve({ foo: 1 }), { + // @ts-expect-error cached data should return the same as value of fetcher + getCachedData: () => ({ bar: 2 }), + }) + useAsyncData<{ foo: number }, unknown, { foo: number }>('test', () => Promise.resolve({ foo: 1 }), { + // @ts-expect-error cached data should return the same as asserted type of `useAsyncData` + getCachedData: () => ({ bar: 2 }), + }) + }) }) describe('app config', () => {