T
TanStack2y ago
sensitive-blue

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
sensitive-blue
sensitive-blueOP2y 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.
robust-apricot
robust-apricot2y ago
Can you do an minimal typescript playground?

Did you find this page helpful?