Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

only null Type is allowed to useAsyncData's default Type #21277

Closed
qoo1476 opened this issue May 31, 2023 · 8 comments
Closed

only null Type is allowed to useAsyncData's default Type #21277

qoo1476 opened this issue May 31, 2023 · 8 comments

Comments

@qoo1476
Copy link

qoo1476 commented May 31, 2023

Environment



Reproduction

i tried to reproduction but it doesn't show typescript error

Describe the bug

sorry my english is bad...

when i use useAsyncData with default data

type User = {
  name: string
  auth: string
}

const { data, pending, refresh } = useAsyncData<User>(
  () => $fetch('/users/1'),
  {
    default: () => ({
      name: '',
      auth: '',
    }),
  },
)

it shows typescript error

so i checked useAsyncData's Type

export declare function useAsyncData<ResT, DataE = Error, DataT = ResT, PickKeys extends KeysOf<DataT> = KeysOf<DataT>, DefaultT = null>(handler: (ctx?: NuxtApp) => Promise<ResT>, options?: AsyncDataOptions<ResT, DataT, PickKeys, DefaultT>): AsyncData<PickFrom<DataT, PickKeys> | DefaultT, DataE | null>;

there are two ways i found

  1. don't use default option or (awalys return null value [X]mean nothing)
const { data, pending, refresh } = useAsyncData<User>(
  () => $fetch('/users/1'),
  {
    default: () => null
  },
)
  1. generate default Type
const { data, pending, refresh } = useAsyncData<
  User,
  Error,
  User,
  KeysOf<User>,
  User <= [ here is default option's type ]
>(() => $fetch('/users/1'), {
  default: () => ({
    name: '',
    auth: '',
  }),
})

so i wonder it's any reason to default option's default type is null ?
i think it could be better with

DefaultT = null    =>   DefaultT = DataT [or] DefaultT = null|DataT

or i awalys have to generate default type when use useAsyncData

and i also checked nuxt.com api document and it looks like what i said

image

sorry if i was wrong and thank you for the amazing job!

Additional context

No response

Logs

No response

Copy link
Member

I'm not 100% sure what you mean. Is the issue that when you provide a default value, the type of data is Ref<Value> rather than Ref<Value | null>?

@aaharu
Copy link
Contributor

aaharu commented May 31, 2023

I think that you probably will avoid typescript errors in this way.

  const { data, pending, refresh } = useAsyncData(() => $fetch<User>('/users/1'), {
    default: (): User => ({
      name: '',
      auth: '',
    }),
  })

@qoo1476
Copy link
Author

qoo1476 commented Jun 1, 2023

@danielroe sorry if my sentences confusing you. English is so hard to me😢
i mean Ref< Value > or Ref<Value | null> both is all ok. but when i checked useAsyncData type. it's not Ref<Value | null> but just null (for default)

here is part of asyncData.d.ts

export declare function useAsyncData<ResT, DataE = Error, DataT = ResT, PickKeys extends KeysOf<DataT> = KeysOf<DataT>, DefaultT = null>(handler: (ctx?: NuxtApp) => Promise<ResT>, options?: AsyncDataOptions<ResT, DataT, PickKeys, DefaultT>): AsyncData<PickFrom<DataT, PickKeys> | DefaultT, DataE | null>;

image

export interface AsyncDataOptions<ResT, DataT = ResT, PickKeys extends KeysOf<DataT> = KeysOf<DataT>, DefaultT = null> {
    server?: boolean;
    lazy?: boolean;
    default?: () => DefaultT | Ref<DefaultT>;
    transform?: _Transform<ResT, DataT>;
    pick?: PickKeys;
    watch?: MultiWatchSources;
    immediate?: boolean;
}

@aaharu thank you for your answer but it still does not work

maybe something wrong in my develope environment?

i'm work with visual studio code with volar

currently the only way i found is

const { data, pending, refresh } = useAsyncData<
  User,
  Error,
  User,
  KeysOf<User>,
  User
>(() => $fetch('/users/1'), {
  default: () => ({
    name: '',
    auth: '',
  }),
})

@Applelo
Copy link

Applelo commented Jun 19, 2023

It seems like I have the same problem:

image
with

await useAsyncData<Taxon[]>('brands', () =>
    $fetchApi('/api/v2/shop/taxons'), 
    {
       default: () => [],
    }
)

I have tried to pass Taxon[] (Taxon is a typescript interface) like @aaharu mentionned but it didn't work :/ It appears when I have upgrade my version of Nuxt to 3.3 to 3.5 (maybe a typing change in useAsyncData).

@danielroe
Copy link
Member

Would you provide a code reproduction? 🙏

@aaharu
Copy link
Contributor

aaharu commented Jun 20, 2023

@Applelo
The method I have shown is to specify no type argument for useAsyncData.
Would this still result in an error?

await useAsyncData('brands', () =>
    $fetchApi('/api/v2/shop/taxons') as Promise<Taxon[]>, 
    {
       default: (): Taxon[] => [],
    }
)

@Applelo
Copy link

Applelo commented Jun 20, 2023

@aaharu Ok so I have move the <Taxon[]> inside the useAsyncData to my $fetchApi (a ofetch object) and now it works fine with this code.

useAsyncData('brands', () =>
    $fetchApi<Taxon[]>('/api/v2/shop/taxons'), 
    {
    default: () => [],
  })

I don't know if it's relevant to do a reproduction ? Should my previous code work with typing pass in useAsyncData like this ?

useAsyncData<Taxon[]>()

If so, I can make a reproduction.

@qoo1476
Copy link
Author

qoo1476 commented Jun 29, 2023

@aaharu

it's still not solved to me.... so can i ask a one?

tell me if i was wrong.

this is from #20968

in asyncData type

https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/composables/asyncData.ts

i see all DefaultT's initial type is null
and DefaultT is used default parameter's return type
here is one piece of example from asyncData.ts

export interface AsyncDataOptions<
  ResT,
  DataT = ResT,
  PickKeys extends KeysOf<DataT> = KeysOf<DataT>,
  DefaultT = null, // this Line, DefaultT's initial type is null
> {
  server?: boolean
  lazy?: boolean
  default?: () => DefaultT | Ref<DefaultT> // and default parameter return type is DefaultT(and it's null initially)
  transform?: _Transform<ResT, DataT>
  pick?: PickKeys
  watch?: MultiWatchSources
  immediate?: boolean
}

...

for fix this type problem, all these DefaultT's initial type sholdn't be follow Data's type?
like bottom code

export interface AsyncDataOptions<
  ResT,
  DataT = ResT,
  PickKeys extends KeysOf<DataT> = KeysOf<DataT>,
  // DefaultT = null,
  DefaultT = DataT (or ResT?)
> {
  server?: boolean
  lazy?: boolean
  default?: () => DefaultT | Ref<DefaultT>
  transform?: _Transform<ResT, DataT>
  pick?: PickKeys
  watch?: MultiWatchSources
  immediate?: boolean
}

export function useAsyncData<
  ResT,
  DataE = Error,
  DataT = ResT,
  PickKeys extends KeysOf<DataT> = KeysOf<DataT>,
  // DefaultT = null,
  DefaultT = DataT
> (
  handler: (ctx?: NuxtApp) => Promise<ResT>,
  options?: AsyncDataOptions<ResT, DataT, PickKeys, DefaultT>
): AsyncData<PickFrom<DataT, PickKeys> | DefaultT, DataE | null>

.... more about all DefaultT type

please check this one if you have any times. thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants