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.
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.
Let's say I have api/profile (which has `.posts`) and api/user-directory (which does not). I define User as a discriminated union - one has type `user-with-posts` and one has type `user-no-posts`. OK, good so far. But now say I have a photo gallery, which returns photos on user. Now I have to add that into my discriminated union type, e.g. `user-with-posts-and-photos`, `user-with-posts-but-not-photos`, `user-with-no-posts-but-yes-photos`... and it gets worse if I also have another page with DMs...
Typescript playground: https://www.typescriptlang.org/play/?#code/C4TwDgpgBACg9gZ2F...
So {user: {...}, photos: [...]}, not {user: {..., photos: [...]}}.
Alternatively define separate schemas for each endpoint that extend the base User schema. But I'd prefer having the same structure everywhere as much as possible.
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.