Kong / swrv

Stale-while-revalidate data fetching for Vue

Home Page:https://docs-swrv.netlify.app

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Possible `key` type mismatch

mv-go opened this issue · comments

commented

According to docs something like this should be possible:
image

However, the following code triggers a TS type mismatch warning

const maybeUndefined = ref<string>()

const { data, error, mutate } = useSWRV(
  () => maybeUndefined.value && `my unuque key ${maybeUndefined.value}`,
  async () => {
    const r = await axiosInstance.get(`myUrl/${maybeUndefined.value}`)
    return r
  },
)

Warning reads:

Argument of type '() => string | undefined' is not assignable to parameter of type 'IKey'.
  Type '() => string | undefined' is not assignable to type 'keyFunction'.ts(2345)

Upon further digging the issue seems to be in type declaration for keyFunction

export declare type keyType = string | any[] | null;
declare type keyFunction = () => keyType;
export declare type IKey = keyFunction | keyType;

It would seem that amending keyType to

export declare type keyType = string | any[] | null | undefined;

would fix the issue.

However I'm not sure if this doesn't break something down the line :)

commented

ATM I'm working around this by explicitly returning null in the keyFunction where necessary, however it'd be great to be able to return null || undefined as documentation states

I think if you defined your original const differently it would pass the checks:

const maybeUndefined = ref<string>('')

// or as null without even declaring a type
const maybeUndefined = ref(null)

But you're saying you should be able to define an "empty" ref, meaning it should be able to be undefined, which I think makes sense, because these should both eval to a falsy value:

const user = ref()
const { data: projects } = useSWRV(() => user.value && '/api/projects?uid=' + user.value.id, fetch)

const user = ref<string>('')
const { data: projects } = useSWRV(() => user.value && '/api/projects?uid=' + user.value.id, fetch)

However I'm not sure if this doesn't break something down the line

I'm more concerned about breaking the interface for IKey which it looks like cannot evaluate to undefined

commented

Yes, I agree - this could be a breaking change. Speaking of which, I would consider switching the behaviour from falsy to strictly null || undefined. Consider the following case:

const id = ref<number>() // undefined
const { data } = useSWRV(
  () => id.value && `/posts/${id.value}`,
  fetch
)
id.value = 0 // not undefined, but still falsy

In this case, the fetch would not be triggered, however a post (a user, an object) with an id = 0 is a perfectly valid case.

However, maybe in this case, leaving the developer to explicitly return null might be actually not that bad of an idea :)

n this case, the fetch would not be triggered, however a post (a user, an object) with an id = 0 is a perfectly valid case.

In JavaScript, 0 is considered a falsy value. Source

commented

In JavaScript, 0 is considered a falsy value. Source

I understand, yes. So in my example above you would suggest that fetch should not be triggered when id is changed from undefined to 0?

So in my example above you would suggest that fetch should not be triggered when id is changed from undefined to 0?

Correct, because they both evaluate as falsy.

commented

Is this a desired behaviour?

It would seem common to have an object on the backend with an id = 0

Instead of thinking about something with an id, think about an iterator.

If I have a starting value of an iterator as let i = 0 and increment in a loop or something when I have data and/or processing something, I'd only want the fetcher to run when the value of i is non-falsy (i.e. not 0).

I see your use-case; however, I would think if you know you're dealing with falsy values coming from your data structure you would use something you know that cannot equate to falsy as your dependent fetcher key.

commented

Fair enough. Should we consider implementing changes regarding my initial message in this issue - to include undefined in typings. Or shall we just close this one as irrelevant? :)

I'm still wondering if adding undefined to keyType invalidates the IKey interface