diff --git a/packages/nuxt/src/app/composables/asyncData.ts b/packages/nuxt/src/app/composables/asyncData.ts index 75d21f30a4..eba8f205a5 100644 --- a/packages/nuxt/src/app/composables/asyncData.ts +++ b/packages/nuxt/src/app/composables/asyncData.ts @@ -13,7 +13,14 @@ export type PickFrom> = T extends Array : Pick : T -export type KeysOf = Array +export type KeysOf = Array< + T extends T // Include all keys of union types, not just common keys + ? keyof T extends string + ? keyof T + : string + : never +> + export type KeyOfRes = KeysOf> type MultiWatchSources = (WatchSource | object)[] diff --git a/test/fixtures/basic/server/api/union.ts b/test/fixtures/basic/server/api/union.ts new file mode 100644 index 0000000000..9358a00ecc --- /dev/null +++ b/test/fixtures/basic/server/api/union.ts @@ -0,0 +1,4 @@ +export default defineEventHandler(() => ({ + type: 'a', + foo: 'bar' +}) as { type: 'a', foo: string } | { type: 'b', baz: string }) diff --git a/test/fixtures/basic/types.ts b/test/fixtures/basic/types.ts index a73c8738f2..db32fda10d 100644 --- a/test/fixtures/basic/types.ts +++ b/test/fixtures/basic/types.ts @@ -17,6 +17,7 @@ describe('API routes', () => { it('generates types for routes', () => { expectTypeOf($fetch('/api/hello')).toEqualTypeOf>() expectTypeOf($fetch('/api/hey')).toEqualTypeOf>() + expectTypeOf($fetch('/api/union')).toEqualTypeOf>() expectTypeOf($fetch('/api/other')).toEqualTypeOf>() expectTypeOf($fetch('/test')).toEqualTypeOf>() }) @@ -25,6 +26,8 @@ describe('API routes', () => { expectTypeOf(useAsyncData('api-hello', () => $fetch('/api/hello')).data).toEqualTypeOf>() expectTypeOf(useAsyncData('api-hey', () => $fetch('/api/hey')).data).toEqualTypeOf>() expectTypeOf(useAsyncData('api-hey-with-pick', () => $fetch('/api/hey'), { pick: ['baz'] }).data).toEqualTypeOf>() + expectTypeOf(useAsyncData('api-union', () => $fetch('/api/union')).data).toEqualTypeOf>() + expectTypeOf(useAsyncData('api-union-with-pick', () => $fetch('/api/union'), { pick: ['type'] }).data).toEqualTypeOf>() expectTypeOf(useAsyncData('api-other', () => $fetch('/api/other')).data).toEqualTypeOf>() expectTypeOf(useAsyncData('api-generics', () => $fetch('/test')).data).toEqualTypeOf>() @@ -34,6 +37,8 @@ describe('API routes', () => { expectTypeOf(useLazyAsyncData('lazy-api-hello', () => $fetch('/api/hello')).data).toEqualTypeOf>() expectTypeOf(useLazyAsyncData('lazy-api-hey', () => $fetch('/api/hey')).data).toEqualTypeOf>() expectTypeOf(useLazyAsyncData('lazy-api-hey-with-pick', () => $fetch('/api/hey'), { pick: ['baz'] }).data).toEqualTypeOf>() + expectTypeOf(useLazyAsyncData('lazy-api-union', () => $fetch('/api/union')).data).toEqualTypeOf>() + expectTypeOf(useLazyAsyncData('lazy-api-union-with-pick', () => $fetch('/api/union'), { pick: ['type'] }).data).toEqualTypeOf>() expectTypeOf(useLazyAsyncData('lazy-api-other', () => $fetch('/api/other')).data).toEqualTypeOf>() expectTypeOf(useLazyAsyncData('lazy-api-generics', () => $fetch('/test')).data).toEqualTypeOf>() @@ -45,6 +50,8 @@ describe('API routes', () => { expectTypeOf(useFetch('/api/hello').data).toEqualTypeOf>() expectTypeOf(useFetch('/api/hey').data).toEqualTypeOf>() expectTypeOf(useFetch('/api/hey', { pick: ['baz'] }).data).toEqualTypeOf>() + expectTypeOf(useFetch('/api/union').data).toEqualTypeOf>() + expectTypeOf(useFetch('/api/union', { pick: ['type'] }).data).toEqualTypeOf>() expectTypeOf(useFetch('/api/other').data).toEqualTypeOf>() expectTypeOf(useFetch('/test').data).toEqualTypeOf>() @@ -54,7 +61,8 @@ describe('API routes', () => { expectTypeOf(useLazyFetch('/api/hello').data).toEqualTypeOf>() expectTypeOf(useLazyFetch('/api/hey').data).toEqualTypeOf>() expectTypeOf(useLazyFetch('/api/hey', { pick: ['baz'] }).data).toEqualTypeOf>() - expectTypeOf(useLazyFetch('/api/other').data).toEqualTypeOf>() + expectTypeOf(useLazyFetch('/api/union').data).toEqualTypeOf>() + expectTypeOf(useLazyFetch('/api/union', { pick: ['type'] }).data).toEqualTypeOf>() expectTypeOf(useLazyFetch('/api/other').data).toEqualTypeOf>() expectTypeOf(useLazyFetch('/test').data).toEqualTypeOf>()