T
TanStack•6mo ago
like-gold

Inference lost in server function

Hello, I'm quite new to typescript but I don't understand this case where I have a middleware which, using its own validator return typed data but: - If just after the middleware i connect it to the .handler then the types are correctly inferred for data. - If I use the server function .validator after the middleware then the type of data is lost.
// --- CLIENT -----

// My tanstack queryOptions
export const profileOptions = (username: string) => queryOptions({
queryKey: queryKeys.profileKey(username),
queryFn: () => getUserProfile({ data: { username } }),
});

// --- SERVER -----

interface BaseDataWithUsername {
username: string;
[key: string]: any;
}

export const authorizationMiddleware = createMiddleware()
.validator((rawData: unknown): BaseDataWithUsername => {
if (typeof rawData !== "object" || rawData === null) throw new Error("Bad request");
const data = rawData as Record<string, any>;
if (!data.username) throw notFound();
return data as BaseDataWithUsername; // Here I type data
})
.server(async ({ next, data: { username } }) => {
// whatever but here username and data are nicely typed, yay :)
return next({ context: { user: user, currentUser: session?.user } });
});


export const getUserProfile = createServerFn({ method: "GET" })
.middleware([authorizationMiddleware])
.validator((data) => data) // data here is `any` why ?
// but if this validator is not present then the data in .handler will be inferred to have at least username: string, and [key: string]: any;
.handler(async ({ context: { currentUser, user }, data }) => {
// something something
});
// --- CLIENT -----

// My tanstack queryOptions
export const profileOptions = (username: string) => queryOptions({
queryKey: queryKeys.profileKey(username),
queryFn: () => getUserProfile({ data: { username } }),
});

// --- SERVER -----

interface BaseDataWithUsername {
username: string;
[key: string]: any;
}

export const authorizationMiddleware = createMiddleware()
.validator((rawData: unknown): BaseDataWithUsername => {
if (typeof rawData !== "object" || rawData === null) throw new Error("Bad request");
const data = rawData as Record<string, any>;
if (!data.username) throw notFound();
return data as BaseDataWithUsername; // Here I type data
})
.server(async ({ next, data: { username } }) => {
// whatever but here username and data are nicely typed, yay :)
return next({ context: { user: user, currentUser: session?.user } });
});


export const getUserProfile = createServerFn({ method: "GET" })
.middleware([authorizationMiddleware])
.validator((data) => data) // data here is `any` why ?
// but if this validator is not present then the data in .handler will be inferred to have at least username: string, and [key: string]: any;
.handler(async ({ context: { currentUser, user }, data }) => {
// something something
});
If someone can explain to me this typescript behavior 🙂
3 Replies
xenial-black
xenial-black•6mo ago
cc @Chris Horobin
like-gold
like-goldOP•6mo ago
So is this a normal behavior or ? 🙂
xenial-black
xenial-black•6mo ago
don't think so. can you please create a GitHub issue for that?

Did you find this page helpful?