T
TanStack2w ago
stormy-gold

Potential Solution for Support for Tagged Types in `ParseJSON` Type

I just wanted to post this here since it would very likely get missed since it is an old post, and I figure here might be a more reasonable place to get an answer: https://github.com/TanStack/router/issues/4005#issuecomment-3327007509 Effectively, I have an approach with Interface merging that may enable the router to support parsing tagged types at a type level, where currently it instead treats them as non-stringifiable and requires a patch for any given tagged/opaque type implementation. My main questions are: 1. Given my solution provided in the GitHub thread, is this something conceptually that Tanstack would like to pursue (I can see the argument that the "API" of such functionality is quite complicated for a majority of developers, but on the other hand, could be put at the bottom of the typescript docs section, and effectively requires 0 attention from people that do not require the functionality) 2. If this is an API that would be useful, would you like me to create a PR (Don't want to go ahead with that if it's just going to waste people's time, so thought I should clarify first) 3. I have a suspicion that this could have the potential to add some typescript performance overhead since it requires an infer which I roughly understand to be a more "expensive" operation in typescript (at least from my current knowledge level) and therefore. Is this something that I can realistically verify while making a PR, or is it more of a "yolo" situation? Note: I am posting here, but this fix would apply for both start and router since it modifies the underlying ParseJSON type if I were to go ahead with it.
GitHub
Missing support for Tagged types in Server Function response · Iss...
Which project does this relate to? Start Describe the bug If a server function response includes a Tagged/Branded type type AccountId = Tagged<string, 'AccountId'> declare const tag: ...
8 Replies
rare-sapphire
rare-sapphire7d ago
at least this seems to work now: https://github.com/TanStack/router/issues/3157
GitHub
types: createServerFn does not accept branded strings · Issue #315...
Which project does this relate to? Start Describe the bug Code: export const listWidgets = createServerFn({ method: "GET" }).handler( async () => { return [ { id: "1" as stri...
stormy-gold
stormy-goldOP7d ago
Interesting, I’m surprised that didn’t work originally since it only used primitives. The main problem with most branded types is that they rely on symbols. Outside of type-fest, tanstack queries QueryKey made using queryOption also suffers from this issue. What are your thoughts on this approach? I think it would require a “Register<T>” interface that is provided from tanstack end
rare-sapphire
rare-sapphire7d ago
can you provide a full example that currently does not work?
stormy-gold
stormy-goldOP7d ago
I've updated the repro with this example as well now: https://stackblitz.com/edit/tanstack-router-op1tmyk6?file=src%2Futils%2Faccount.tsx For clarity, I fully expect the type to tell me that it's not serializable, since most tagged typed implementations use a symbol as a key which is not serializable, my suggestion for a fix is just a way for consumers to explicitly handle specific tagged type implementations so they do not need to disable the serializable check throughout the code base, and instead have an actual way to work around the problem. The updated example includes it working for a primitive, but not for a type-fest tagged type, as well as for a Tanstack query queryKey.s
StackBlitz
Tanstack serverFn with Tagged types (duplicated) - StackBlitz
Run official live example code for Router Start Basic, created by Tanstack on StackBlitz
stormy-gold
stormy-goldOP7d ago
Just to simplify my question: In my opinion, the only way for the router to support tagged types is to offer a generic register interface that can have a unwrap or unwrappedTag key on it that can be used within the ParseJSON function. I suspect this would basically involve Tanstack having an interface on top of the base Register interface
interface Register {}
interface GenericRegister<T> {}
interface Register {}
interface GenericRegister<T> {}
Then for consumers to use this to support specific tagged types, they would essentially write an unwrap type and register it on the interface
// userland
interface GenericRegister<T> {
unwrappedTag: MyUnwrappedTag<T>
}
// userland
interface GenericRegister<T> {
unwrappedTag: MyUnwrappedTag<T>
}
Is this something you would like me to implement and make a PR for so that users can have tagged type support, or is this interface/API for supporting it too "clunky" for something exposed to the user? I think implementing it will be pretty straight forward, especially given the scope for now can be limited to the ParseJSON type, so happy to make a PR, I just wanted to clarify if this is even something that you want
rare-sapphire
rare-sapphire6d ago
using latest start version i dont get a type error in your example. can you please check?
stormy-gold
stormy-goldOP6d ago
I apologize for wasting your time, I should've checked the latest router version... This can probably just be ignored then. I do want to clarify though -Is it actually possible to send symbols from the server to the client? I understand that it's not giving a type error - but I would expect that it should be impossible to actually send a symbol over the wire - since it is unique. Is this actually handled by Tanstack start?
rare-sapphire
rare-sapphire6d ago
you can use a custom serialization adapter if you want to actually handle symbols at runtime

Did you find this page helpful?