T
TanStack2mo ago
national-gold

type broken on useServerFn?

Sorry for the AI generated summary, but just wanted a clean reproducible version of the issue:
import { useMutation } from "@tanstack/react-query";
import { useServerFn } from "@tanstack/react-start";

type SigninInput = { email: string; password: string };
type SigninResult = { user: { id: string; name: string }; token: string };

function signin$(args: { data: SigninInput }): Promise<SigninResult> {
return Promise.resolve({
user: { id: "123", name: "John Doe" },
token: "abc",
});
}

// Case 1: Inline use — causes type issue (data is `unknown`)
const inlineCase = useMutation({
mutationFn: useServerFn(signin$),
onSuccess: (data) => {
// @ts-expect-error — data is `unknown`
console.log(data.user.id);
},
});

inlineCase.mutate({ data: { email: "a@b.com", password: "123456" } });

// Case 2: Const-first use — fixes the type issue
const serverFn = useServerFn(signin$);

const constCase = useMutation({
mutationFn: serverFn,
onSuccess: (data) => {
const idUpper = data.user.id.toUpperCase();
console.log("constCase:", idUpper);
},
});

constCase.mutate({ data: { email: "a@b.com", password: "123456" } });
import { useMutation } from "@tanstack/react-query";
import { useServerFn } from "@tanstack/react-start";

type SigninInput = { email: string; password: string };
type SigninResult = { user: { id: string; name: string }; token: string };

function signin$(args: { data: SigninInput }): Promise<SigninResult> {
return Promise.resolve({
user: { id: "123", name: "John Doe" },
token: "abc",
});
}

// Case 1: Inline use — causes type issue (data is `unknown`)
const inlineCase = useMutation({
mutationFn: useServerFn(signin$),
onSuccess: (data) => {
// @ts-expect-error — data is `unknown`
console.log(data.user.id);
},
});

inlineCase.mutate({ data: { email: "a@b.com", password: "123456" } });

// Case 2: Const-first use — fixes the type issue
const serverFn = useServerFn(signin$);

const constCase = useMutation({
mutationFn: serverFn,
onSuccess: (data) => {
const idUpper = data.user.id.toUpperCase();
console.log("constCase:", idUpper);
},
});

constCase.mutate({ data: { email: "a@b.com", password: "123456" } });
7 Replies
national-gold
national-goldOP2mo ago
Do we have to do this? const serverFn = useServerFn(signin$); always?
funny-blue
funny-blue2mo ago
weird inference issue :ThinkSpin: what's the problem with that though ?
national-gold
national-goldOP2mo ago
Using Server Functions and Tanstack Query
A website containing blog posts related to the frontend.
national-gold
national-goldOP2mo ago
and wanted to confirm if this is a bug, if it's by design I think we should add it in the docs that we will loose the type inference otherwise, dont you think so? All dependencies are latest
like-gold
like-gold2mo ago
can you please create a github issue for this? even if this cannot be solved eventually (due to how type inference works) it's still helpful for documentation purposes
national-gold
national-goldOP2mo ago
Sure, I'll create a demo and if someone confirm it's how it works by design I can create a MR to add it to the docs. Thanks @Manuel Schiller
national-gold
national-goldOP2mo ago
Raised a bug just to get some feedback, maybe Im doing something wrong https://github.com/TanStack/router/issues/5352
GitHub
Broken type for useServerFn · Issue #5352 · TanStack/router
Which project does this relate to? Router Describe the bug Hi, I think the type is broken for the useServerFn. I&#39;ve reproduced and noticed that if I need to use the onSuccess callback I loose t...

Did you find this page helpful?