T
TanStack2y ago
correct-apricot

Modifying the type of mutateAsync's

I'm doing an optimistic update when adding an entry to a table and calling mutateAsync with partial data for that entry. However, the type for the variables of the mutateAsync function seem to be the same as each element in my useQuery result, and this gives me a type error, because I'm leaving out a bunch of fields that the database will eventually default to. Specifically, I have this:
const { mutateAsync: addDataExport } = useMutation({
mutationFn: (newDataExport: DataExportInsert) => queueDataExport(newDataExport),
onMutate: async (newDataExport: DataExport) => {
await queryClient.cancelQueries({ queryKey });
const previousData = queryClient.getQueryData(queryKey);

queryClient.setQueryData(queryKey, (old: DataExport[]) => {
old.unshift(newDataExport);

return old;
});

return { previousData };
},
const { mutateAsync: addDataExport } = useMutation({
mutationFn: (newDataExport: DataExportInsert) => queueDataExport(newDataExport),
onMutate: async (newDataExport: DataExport) => {
await queryClient.cancelQueries({ queryKey });
const previousData = queryClient.getQueryData(queryKey);

queryClient.setQueryData(queryKey, (old: DataExport[]) => {
old.unshift(newDataExport);

return old;
});

return { previousData };
},
DataExport requires certain keys, but if I leave those out, Drizzle will set defaults, so I want variables to be of DataExportInsert instead. I tried explicitly setting the type like this:
type AddDataExportVariables = UseMutateAsyncFunction<
DataExport[],
Error,
DataExportInsert,
{
previousData: unknown;
}
>;

const { mutateAsync: addDataExport }: { mutateAsync: AddDataExportVariables } = useMutation({...
type AddDataExportVariables = UseMutateAsyncFunction<
DataExport[],
Error,
DataExportInsert,
{
previousData: unknown;
}
>;

const { mutateAsync: addDataExport }: { mutateAsync: AddDataExportVariables } = useMutation({...
...but that gives me a new error, ultimately saying Types of parameters variables and variables are incompatible.. So for now, I just explicitly set all the optional variables to null like Drizzle will end up doing, but I wonder if there's a better way to set the type.
2 Replies
correct-apricot
correct-apricotOP2y ago
I.e. I'm doing this (with addDataExport being the mutateAsync function:
addDataExport({
id: '',
survey,
source,
distribution,
variant,
status: 'queued',
userId,
limit: null,
startTime: null,
endTime: null,
requestedAt: new Date(),
url: null,
size: null,
statusMessage: null,
rowCount: null,
sampleRows: null,
completedAt: null,
exportTime: null,
});
addDataExport({
id: '',
survey,
source,
distribution,
variant,
status: 'queued',
userId,
limit: null,
startTime: null,
endTime: null,
requestedAt: new Date(),
url: null,
size: null,
statusMessage: null,
rowCount: null,
sampleRows: null,
completedAt: null,
exportTime: null,
});
...when I'd rather be doing this:
addDataExport({
id: '',
survey,
source,
distribution,
variant,
status: 'queued',
userId,
requestedAt: new Date(),
});
addDataExport({
id: '',
survey,
source,
distribution,
variant,
status: 'queued',
userId,
requestedAt: new Date(),
});
Hmm, looks like it's the type on onMutate that it uses. So I did this:
const { mutateAsync: addDataExport } = useMutation({
mutationFn: (newDataExport: DataExportInsert) => queueDataExport(newDataExport),
onMutate: async (newDataExport: DataExportInsert) => {
await queryClient.cancelQueries({ queryKey });
const previousData = queryClient.getQueryData(queryKey);

queryClient.setQueryData(queryKey, (old: DataExportInsert[]) => {
old.unshift(newDataExport);

return old;
});

return { previousData };
},
const { mutateAsync: addDataExport } = useMutation({
mutationFn: (newDataExport: DataExportInsert) => queueDataExport(newDataExport),
onMutate: async (newDataExport: DataExportInsert) => {
await queryClient.cancelQueries({ queryKey });
const previousData = queryClient.getQueryData(queryKey);

queryClient.setQueryData(queryKey, (old: DataExportInsert[]) => {
old.unshift(newDataExport);

return old;
});

return { previousData };
},
I did have to type old in setQueryData as DataExportInsert[] even though technically it's mostly DataExport[] (i.e. useQuery TData), which feels a little off, but it works.
national-gold
national-gold2y ago
Can you do an minimal typescript playground?

Did you find this page helpful?