Live data from Hacker News

tRPC – Build and consume typesafe APIs without schemas or code generation

trpc.io

191–200 of 223 posts

Re: tRPC – Build and consume typesafe APIs without schemas or code generation

#192
post #51

Earlier quoted context omitted.

I'm not too surprised. Most people for whom TypeScript is an option won't have been exposed to generations of RPCs that fail to deliver simplicity. So it isn't going to be on their radar. I've been using gRPC and REST'ish+JSON APIs for years now and what I find puzzling is that REST+JSON tends to mean a lot more work, less pleasing code than gRPC, and yet people prefer it. Not because it leads to simpler, better, fas…

People sticking with REST+Json usually don't want to have a compilation step for the API exchanges layer. That means more validation and worse tooling, but also better legacy and potentially future compatibility, and way easier debugging at any stage. I feel this is the same debate between scripting languages and compiled languages, both provide different trade-offs and I don't think we'll see one completely disappea…

> People sticking with REST+Json usually don't want to have > a compilation step for the API exchanges layer.

Hmm. I'm not sure what you are saying.

The way people tend to try to consume REST APIs is by generating client (and/or server code) from a spec. For instance OpenAPI 2.0. At least on Go the tooling for that leaves something to be desired, and the generated code isn't exactly beautiful. So you either depend on a library that someone generates from the spec, and then shares, or you generate it yourself.

(We do this for a bunch of languages for our APIs, and the clients are ... not uniformly beautiful :-))

If we're talking about writing the REST client by hand...well...I'm not sure why one would want to do that. (Nor am I sure that's what you meant, so I'm not accusing you of that).

My current workflow (in Go) for consuming gRPC interfaces is to use the buf.build package proxy. Which means I just add an import, run go mod tidy, and I'm good. I don't even need the tooling installed. As I think it should be.

I suppose this could be done for OpenAPI 2.0 too. You stuff OpenAPI 2.0 specs in and you get code for a bunch of languages out. (Someone must surely have built this already?)

Re: tRPC – Build and consume typesafe APIs without schemas or code generation

#193

Earlier quoted context omitted.

Agreed. Although, sometimes it feels like this is a losing battle. I've worked with too many people who see that level of separation as "unneeded duplication", with constant complaints about having to update a bunch of different layers "just to add a new field. IMO, at a minimum, you have your API layer model, your internal model, and your database model with a mapping layer at each boundary. I rarely have problems w…

I think there are certain types of boilerplate that used to be truly onerous that are now much less so because of types. If there are 3 different files that need to be updated to add a file, and forgetting one is only going to error at runtime (maybe even only if you're exercising that new field) that's horrible. But 3 files that require updating where the code won't compile until you've added all three is way way le…

> But 3 files that require updating where the code won't compile until you've added all three is way way less of a problem.

I think this is only really possible in a relatively small subset of programming languages, even among those with static typing. At a minimum it seems like it would require a type system that didn't allow optional properties (by default) and did distinguish between nullable and non-nullable types.

Unless I'm missing something. Would love to see some examples of this done right. Or at least examples of languages you've done this in.

Re: tRPC – Build and consume typesafe APIs without schemas or code generation

#194
post #158
post #149

Earlier quoted context omitted.

If you only ever use Typescript and are sure you’ll never need to interact with the code in any other language or service in a different repo it’s fine. But as soon as you need to reuse that backend for anything else you’re stuck building something new.

You can make calls to tRPC endpoints from anything that can send an HTTP request. The RPC format for requests might not be your cup of tea, but it works.

Ostensibly, the product isn't as useful as the existing gotos (json schemas, shared libraries, graphql, etc), if you cannot create a shareable schema for validation. The ability to form arbitrary requests is already assumed. If your messages are very complex, you need some tooling.

Re: tRPC – Build and consume typesafe APIs without schemas or code generation

#196

I've personally been using ts-rest for my projects, which is traditional REST but allows one to autogenerate types and API docs from a zod schema. tRPC seems cool, but seems riskier to go with an alternative to REST or GraphQL, especially if you intend to make your API public and/or have multiple consumers of your API.

I’m also singing ts-rest.com’s praise these days. Admittedly a small project with I have separate packages (in a monorepo) for the “contract definition” and the “API implementation” (which is currently NextJS, but likely Express in the future — and the migration path looks like very smooth sailing)

Request/response validation, OpenAPI spec, fetch & react-query clients without any additional effort. Mocks for tests auto-generate based on contract definition as MSW. It almost feels too good to be true.

Re: tRPC – Build and consume typesafe APIs without schemas or code generation

#197
post #7

We’ve use an API style similar to tRPC at Notion, although our API predated tRPC by 4 years or so. You can build this kind of thing yourself easily using Typescript’s mapped types, by building an object type where the keys are your API names, and the values are { request, response } types. Structure your “server” bits to define each API handler as a function taking APIs[“addUser”][“request”] and returning Promise . T…

This works quite well actually: https://github.com/mikew/transmission-material-ui/blob/maste... https://github.com/mikew/transmission-material-ui/blob/maste...

That's seems to be completely missing validation. Typescript types are at their worst when they are lies, and the actual shape of the data is something completely different.

Re: tRPC – Build and consume typesafe APIs without schemas or code generation

#198

I'm wondering how they handle version skew and migration. Fields have a lifecycle. When they're introduced, no clients or servers know about them. Clients and servers aren't restarted all at once. They won't have the same version of the types. Data will be written using one version of a type and read using a different version. If you can guarantee all binaries, running programs, and data gets upgraded (no persistent…

Pretty much "you do it". Zod can accept unrecognized fields, and then you move to optional fields, and finally once the dust settles you can make the field required.

Of course, the demographic that most desires what tRPC does is the least likely to think about that sort of stuff.

Re: tRPC – Build and consume typesafe APIs without schemas or code generation

#199

Earlier quoted context omitted.

It’s not a perfect mapping with JSON. Everyone knows that stuff like functions and dates can’t go over JSON, but there are also subtler things, like the fact that undefined can’t exist as a value in JSON. I’ve seen codebases get pretty mixed up about the semantics of things like properties being optional versus T | undefined.

> Everyone knows that stuff like functions and dates can’t go over JSON, but there are also subtler things, like the fact that undefined can’t exist as a value in JSON I use `null` for that purpose, and it's been pretty reliable. What are the situations where that falls down?

I also like null | T for required properties, but for whatever reason I have seen that undefined | T is a much more common convention in the TypeScript world. Maybe the reason for that is the semantic about how object access returns undefined, but that’s precisely the source of ambiguity between “object has property X with value undefined” and “object does not have property X”.

Re: tRPC – Build and consume typesafe APIs without schemas or code generation

#200
post #137

Earlier quoted context omitted.

Yes, but those systems have been obscure and uncommon for longer than a lot of today's programmers were even in the field. In the intervening time we all standardized on JSON and rediscovered or reinvented similar concepts all using JSON. Fine. It's great to understand and learn from prior inventions, but it's not like we're all going to switch back to IDL. Consider that JSON being ubiquitous immediately makes it eas…

That’s an interesting statement, because from my vantage point “longevity” seems to be way, way down the priority list for pretty much any technology in JavaScript world. (The major exception being pure JSON.) It feels like if you open any JS codebase from more than 18 months ago, half the libraries will be deprecated or abandoned (not just the version, the entire library). Major patterns and frameworks reinvent them…

So what's wrong with using something based on JSON as the IDL?
Post reply on HN