Type inference gap between Tanstack Start and Tanstack Query
When a TanStack Start loader redirects based on query data (like redirecting if user is null), the runtime guarantees the route will never render in that state.
But TypeScript doesn’t pick that up — it still infers user as User | null in the component.
Problem
The loader guarantees that user isn’t null, but TypeScript doesn’t know that — so you have to use a null assertion or redundant check.
Question
Is there a recommended way to tell TypeScript that the redirect ensures non-null data for this route without null assertions?
8 Replies
adverse-sapphire•4w ago
unless you return loader data I don't see a way
genetic-orangeOP•4w ago
gotcha, that would mean sending the payload twice, which isn't ideal as well.
Guess null assertions is the only way.
adverse-sapphire•4w ago
it wouldn't mean that as our serializer uses reference sharing
but the problem is rather that when consuming the loader data without a query hook no query observer is subscribed
genetic-orangeOP•4w ago
You are right, I just checked the html output, it does seem like only one set of data is included, not sure why I thought it would be loader data + query data.
Regarding query observer, one easy 'fix' is to use fallback value.
i.e.
routeData will please typescript, since it's protected in the runtime by loader.
Right now I'm doing something like this though, i.e. creating a wrapper hook, and throw an error.
do you see any issues with throwing an error in a RouteComponent? ^adverse-sapphire•4w ago
what do you expect to happen when throwing in the component ?
genetic-orangeOP•4w ago
technically it shouldn't happen, as it's protected by the
loader. I'm just wondering if there will be any unexpected behaviour. Currently it renders the errorComponent when I throw the error, which seems right.adverse-sapphire•4w ago
yes that's what should happen. there will be an unavoidable error logged to the browser console btw
genetic-orangeOP•4w ago
gotcha, thanks for the heads up. Though I don't expect it to happen due to runtime guarantees by the loader. Thanks!