top | item 44031235

(no title)

probabletrain | 9 months ago

In an ideal world you'd have one source of truth for what the shape of a User could be (which may well be a discriminated union of User and AnonymousUser or similar).

Without fullstack TS this could look something like: (for a Python backend) Pydantic models+union for the various shapes of `User`, and then OpenAPI/GraphQL schema generation+codegen for the TS client.

discuss

order

johnfn|9 months ago

The problem with this is that your One True User shape tends to have a bunch of optional properties on it. e.g., in the user profile you fetch Post[], but in the user directory you don't, and so on with other joined properties. If every endpoint returns the One True User, then you end up needing to write conditional logic to guard against (say) `.posts` when you fetch users in the profile, even though you know that `.posts` exists.

iainmerrick|9 months ago

In Typescript at least, if the discriminated union is set up correctly, you just need a single check of the type field. That lets TS narrow the type so it knows whether e.g. `.posts` is present or not.

probabletrain|9 months ago

Not sure how other stacks solve this, but with GraphQL the backend defines a `User` type with a full set of fields, and the client specifies only the fields it wants to query. And with codegen you get type safety.

So on the /posts page the client asks for `{ user: { id, posts: { id, content }[] } }`, and gets a generated properly-typed function for making the query.