Nishant Jalan
Nishant Jalan

Reputation: 1038

How to specify useFetch data return type in Nuxt

I am fetching data from an API in Nuxt3. I am using typescript and I wish to define the type of data that I will get. How do I specify this?

<script lang="ts" setup>
  interface APIBody {
    /* properties defined here */
  }

  const {data} = await useFetch("api_url here")
</script>

<template>
 {{ data.name.officialName }}
<template>

I get an error in the template where I am displaying data.name.officialName

Property 'name' does not exist on type 'never'

However, while running the code in the browser, the website works fine.

Edit I tried the following code but I am receiving a different error now.

<script lang="ts" setup>
  interface APIBody {
    /* properties defined here */
  }

  const typedData = ref<APIBody[]>()
  const {data} = await useFetch("api_url here")
  typedData.value = data as APIBody[] // -> error here
</script>

<template>
 {{ data.name.officialName }}
<template>

The error in this case is:

Conversion of type 'Ref<Pick<unknown, never>>' to type 'APIBody[]' may be a mistake because neither type sufficiently overlaps with the other.

Upvotes: 19

Views: 23561

Answers (3)

genter_morgan
genter_morgan

Reputation: 61

It's my working example in Nuxt 3.9.0:

// /api/test.post.ts
export default defineEventHandler(async (event) => {
    const body = await readBody(event);
    return { body };
});

In any component or page:

<script lang="ts" setup>
import type { AsyncData } from 'nuxt/app';
import type { FetchError } from 'ofetch';
    
interface Body { key: string };
    
const { data: { value: { body } }, error } = await useFetch('/api/test', {
  method: 'post',
    body: {
      key: 'value',
    }
  }) as AsyncData<{ body: Body }, FetchError>;
    
// now you're getting body's properties without ts-errors
console.log(body.key); // value
</script>

Upvotes: 5

zalog
zalog

Reputation: 723

If we also need a type based on what is in pick also, you can check this composable:

type SomeProps = {
    prop1: string;
    prop2: string;
};

export function usePropsApi() {
    const { public: { api } } = useRuntimeConfig();

    return {
        read: <T extends keyof SomeProps>({
            pick = [],
        }: {
            pick?: Array<T>;
        } = {}) => useFetch<Pick<SomeProps, T>>('/props', {
            baseURL: api,
            ...(pick.length && pick),
        }),
    };
}

and using like this, props other that the ones from pick[] will be excluded from type:

const { data } = await usePropsApi().read({
    pick: ['prop1'],
});
console.log('data.value: ', data.value?.prop1);
console.log('data.value: ', data.value?.prop2); // Property 'prop2' does not exist on type ...

Upvotes: 1

Under_Koen
Under_Koen

Reputation: 1078

You can give a type to useFetch to define the return type

Like:

  interface APIBody {
    /* properties defined here */
  }

  const {data} = await useFetch<APIBody>("api_url here")

Upvotes: 33

Related Questions