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

fix: fix the type of the argument of KeyedMutator for populateCache #2933

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

Key5n
Copy link

@Key5n Key5n commented Apr 8, 2024

The Problem

I will show you the problem with this code sandbox.
This container uses code sandbox introduced in swr docs with some changes.

I just added TypeScript and changed like below.

export async function addTodo(todo) {
  await delay();
  todos = [...todos, todo];
-  return todos;
+ return todo;
}

In this codesandbox, there is an serious type error:

Argument of type 'Promise<ToDo>' is not assignable to parameter of type 'ToDo[] | Promise<ToDo[] | undefined> | MutatorCallback<ToDo[]> | undefined'.
  Type 'Promise<ToDo>' is not assignable to type 'Promise<ToDo[] | undefined>'.
    Type 'ToDo' is missing the following properties from type 'ToDo[]': length, pop, push, concat, and 25 more.

in the source code:

await mutate(addTodo(newTodo.text), {
  optimisticData: [...(data ?? []), newTodo],
  populateCache: (updatedTodo, todos) => [
    ...(todos ?? []),
    updatedTodo,
  ],
  revalidate: false,
});

I referred to this article.

In this article, the example written in JavaScript uses bound mutate to make addToDo return just one updated item, rather than multiple updated items.
However, when used in TypeScript like the codesandbox I suggested, this results in a type error.
For instance, when useSWR fetches an API that returns a ToDo[] type, the first argument of mutate is expected to be of type ToDo[].
This works fine in JavaScript, but the issue arises only when it's converted to TypeScript.

What this PR does

This PR fixes a type error problem related to populateCache and bound mutate.

Now, the first argument of bound mutate only accepts a type of data fetched by useSWR.

But in order to make use of populateCache, the first argument of mutate should accept any type of API fetching result.

So I changed the type of the first argument from Data (which is the type of data useSWR fetches) into MutationData (which is the type of the data returned by the mutator)

In addition, I changed types in infinite since it had error when I changed the type of KeyedMutator .

Copy link

codesandbox-ci bot commented Apr 8, 2024

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Comment on lines +431 to +435
<Data = any, MutationData = Data>(
key: Arguments,
data?: T | Promise<T> | MutatorCallback<T>,
opts?: boolean | MutatorOptions<Data, T>
): Promise<T | undefined>
data?: MutationData | Promise<MutationData> | MutatorCallback<MutationData>,
opts?: boolean | MutatorOptions<Data, MutationData>
): Promise<MutationData | undefined>
Copy link
Author

@Key5n Key5n Apr 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just refactoring for name consistency.
Since there is @typeParam MutationData comment docs, I think the generics parameter T should follow that.

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

Successfully merging this pull request may close these issues.

None yet

1 participant