Hacker Newsnew | past | comments | ask | show | jobs | submit | more colinmcd's commentslogin

Something like typebox (that's designed to map one-to-one onto JSON Schema) may be better if codegen is a priority.


This is mentioned under "Limitations"

> The result of the macro must be serializable!

> Functions and instances of most classes (except those mentioned above) are not serializable.


Well those are both slightly different than "code". I mean something more like returning an S-expression, or a JS AST object, and having that be inlined. That should have no problem with serialization, since it could just be dropped into the AST (unlike a function or class).



Perhaps? I remember the article arguing more comprehensively why a different order would be beneficial, but maybe I am just misremembering


We already have a Go driver as well[0] and you can get pretty far by executing queries over HTTP[1] though that's not as capable as a full client. As you said, the roadmap needs some freshening up.

[0] https://github.com/edgedb/edgedb-go

[1] https://www.edgedb.com/docs/clients/http/index#edgeql-over-h...


We're still working out the kinks, but some form of this will definitely be possible.

You can already hack this by defining access policies and writing an EdgeQL proxy server that authenticates incoming requests, sets the appropriate global, and forwards the query to the database. There's a Python/Flask implementation of this pattern here[0].

We also have a JavaScript example app demonstrating access policies to simplify authorization logic using Next.js/getServerSideProps[1] and a user management platform you may have heard of called Clerk[2] :)

[0] https://github.com/edgedb/edgedb-examples/tree/main/flask-pr...

[1] https://github.com/edgedb/edgedb-examples/blob/main/nextjs-a...

[2] https://clerk.dev/


EdgeDB is a long-term effort for a DB/query language that's as intuitive as possible for the greatest number of people. The early adopters are primarily those who are frustrated by ORMs and/or SQL, as you'd expect. But you should pick whatever makes you most productive—if you're already productive and happy with SQL, then that's definitely the right choice! Good luck with PureORM, looks very cool.


I think that's a good characterization!


TypeScript's type system is unsound in a mathematical sense: https://effectivetypescript.com/2021/05/06/unsoundness/ Though this has little bearing on practicality which is probably why the original comment is at the bottom of the pile.

He's also using a stricter mathematical definition of "type safety" whereas tRPC means it in the colloquial way it's used in the TypeScript ecosystem (that is, a fully typed interface between client and server, ideally that's non-duplicative and inferred directly from your code instead of being manually defined).


Thanks for clarifying!


Basically tRPC lets you define a router containing all your endpoints in a single structure. Then you can import the type definition of your router and make typed API calls without needing to wire everything together with types.


I wrote the initial proof of concept for tRPC a little over a year ago (though I'm no longer involved in the project). Seems like there's some confusion about how this works. A more complete description is available here[0] below but I'll put a brief explanation below as well.

- It's designed specifically for a full-stack TypeScript app. Your API is implemented as strongly typed server-side functions.

- The input type is specified using a schema library like Zod or io-ts.

- TypeScript infers the return type of these functions.

- You can then import the type signatures of your functions into your client. Just types, no runtime code! This is safe in typescript with the `import type` syntax. tRPC uses those type signatures to provide a typesafe client API, basically an SDK for your API. There's no codegen happening - the client uses TypeScript generics to provide a set of strongly typed "proxy functions" that can be "called" on the client. These proxy functions execute HTTPs requests under the hood: https://trpc.io/docs/rpc

The point is to avoid the boilerplate, codegen, and lack of DRYness associated with building a strongly typed API in TypeScript. You can do this with GraphQL but it relies on code-generation, requires complete buy-in, and (IMO) doesn't provide a great developer experience. TypeScript has a native way of representing types, so the goal is to avoid an intermediate representation (in the form of an OpenAPI spec or GraphQL schema) entirely. As you update your server code, the client's type signatures update instantaneously.

Another important goal is to make it easy to write DRY code when building APIs. Without tRPC, it's common to manually provide type definitions for the results of API calls. But those definitions can easily get out of sync with your actual server code. tRPC infers types from your code itself and provides a typed interface for your API thats doesn't require any manual type annotations.

[0] https://colinhacks.com/essays/painless-typesafety


This is very cool, thanks so much for explaining how this works and, of course, for initiating such a cool project!

As far as I can tell, tRPC basically bridges (hides) network communication and allows doing remote procedure calls almost like regular, type-safe function calls on the same machine within the same process.

Now I would give a fortune for having something like that also for cross-language communication and for communicating with other processes (binaries and shell scripts). I've been thinking about this a lot in recent years: In SWE we need to jump through many hoops only because it's so god damn hard to invoke a function or a whole API living somewhere else in a type-safe manner. Intermediate formats like JSON, protobuf, standards like REST, OpenAPI, and GraphQL, and even languages like SQL (and the various ORM libraries it inspired) are all a result of that to some degree: Once data leaves the safe haven of your (hopefully statically typed) programming language where the compiler/interpreter knows exactly what its type is and what the signature of the function is that you're trying to call, you're basically on your own.

I recently read about WASM Interface Types[0] and it seems like a step in the right direction, though unfortunately it will only bridge the – let's call it – type safety gap between processes, not between different machines in a network.

[0]: https://hacks.mozilla.org/2019/08/webassembly-interface-type...


What's the backwards compatibility story here? What changes to backend function argument and return types can I make without breaking currently-open webpages when I push a new backend instance?


So essentially, it's protobuf but it describes the API instead of a message (which arguably is also an API description) and is for TypeScript on both sides.


Exactly. But with faster iteration speed, more type inference, less overhead, and a TypeScript-native DX.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: