4 ms·
I sorta agree. It can be ridiculously hard to understand and maintain other people’s complicate TS generics. But the payoff is that you have a type system that
by chamomeal 2y ago
I sorta agree. It can be ridiculously hard to understand and maintain other people’s complicate TS generics. But the payoff is that you have a type system that nearly disallows consumers of your interface to use it incorrectly.
Like you’d never get the amazing type safety of libraries like prisma and kysely (an ORM and a query builder) if you couldn’t make such ridiculously expressive generics. But, only a teeny tiny subset of TS devs can work on generics that complex. I definitely can’t!
It’s a tradeoff like anything else.
- ok_dad 2y agoWhat’s an example complex generic? If you have one, that is, I’m curious what kinds of things people do with types. I’m a fan of using types, myself. Thanks in advance.
- bobbylarrybobby 2y agoCheck out the implementations of axum’s Handler trait in Rust. https://docs.rs/axum/0.7.5/axum/handler/trait.Handler.html https://docs.rs/axum/0.7.5/axum/handler/trait.Handler.html
- foresterre 2y agoI sometimes see types in TS with complex generics like [1], but instead of being general like in this example, they're more specific to the type of their values. Couldn't find a proper example on the spot in an open source project. [1] https://github.com/sindresorhus/type-fest/blob/main/source/get.d.ts#L25 https://github.com/sindresorhus/type-fest/blob/main/source/g...
- chamomeal 2y agoHonestly any typescript library with great type safety probably has seriously gnarly generics inside. Here[1] is a random file from kysely, which is surprisingly readable even though kysely's type safety is incredibly good. But things I encounter in the regular non-library world are usually recursive types that have specific constraints. A couple years ago I had my first foray into typescript generics, and was so stumped that I actually gave up. I was trying to map the type of one nested object to another. This[2] is the stackoverflow post from the legendary jcalz that saved me! Check jcalz's link to the TS playground [1]https://github.com/kysely-org/kysely/blob/master/src/query-builder/output-interface.ts https://github.com/kysely-org/kysely/blob/master/src/query-b... [2]https://stackoverflow.com/questions/72461962/is-it-possible-to-recursively-map-one-json-like-type-to-another-in-typescript https://stackoverflow.com/questions/72461962/is-it-possible-...
- Frotag 2y agoCommon usecase is mapping database schemas to "this is what SELECTs / INSERTs" should contain. Honestly most complicated types boil down to a handful of concepts (mapped types, conditionals, recursion) with a few tricks for working around sharp corners (deferring evaluation for performance, controlling whether a union distributes). I've even seen someone solve 8-queens in types using a formal grammar but no clue how that worked. Speaking of, if anyone else has other examples of defining a grammar or ast in typescript, I'd love to see it.
- Frotag 2y agoCommon usecase is mapping database schemas to "this is what SELECTs / INSERTs" should contain. eg https://github.com/jakearchibald/idb https://github.com/jakearchibald/idb Honestly most complicated types boil down to a handful of concepts (mapped types, conditionals, recursion) with a few tricks for working around sharp corners (deferring evaluation for performance, controlling whether a union distributes). I've even seen someone solve 8-queens in types using a formal grammar but no clue how that worked. Speaking of, if anyone else has other examples of defining a grammar or ast in typescript, I'd love to see it.
- steveklabnik 2y agoI don't want to scare you... but here's a function from a codebase at work. https://github.com/oxidecomputer/omicron/blob/5fd1c3588a45adfba0d8c59ff847487b28e6968b/nexus/db-queries/src/db/pagination.rs#L78-L181 https://github.com/oxidecomputer/omicron/blob/5fd1c3588a45ad... That's ninety lines of type constraints.
- chamomeal 2y agoOh god…
- Mawr 2y ago> It’s a tradeoff like anything else. Could not disagree harder with the sentiment. Selling your kidneys for $20 is a tradeoff too. You can't just throw "it's a tradeoff" around as a go-to discussion and critical thought ender.
- chamomeal 2y agolol I actually laughed out loud at that. I might steal your kidneys comparison for certain conversations at work. Didn't mean it as a discussion ender, I think it's the type of tradeoff that anybody really needs to think about when they start down the rabbit hole of crafting the perfect generic type. Like for day to day stuff, I agree with the grug brained developer[1]. But if I'm writing something that needs to be used in a super specific way, I think it's worth the extra effort/complexity to ensure that other devs can't use it incorrectly. I'm usually responsible for making smaller components that other devs can build from, and it's amazing what you can communicate through types.
- 9rx 2y agoYou assert disagreement by repeating what was said using different words? Interesting.
- lenkite 2y agoGenerics would be far less gnarly if language designers adopted Zig-like comptime instead of designing a second mini-language within the main language.
- liampulles 2y agoYes, that's very true. Go tends to be very much leaning on an un-magic approach, so more raw SQL than ORM for example. So as you say I think the two different approaches fit the language ecosystems they are in.
- yencabulator 2y agoMeanwhile, KeystoneJS (a Typescript CMS using Prisma ORM) has such complex generics that I am unable to write a field validation function as standalone, only inline; I simply cannot express the type signature! Ridiculously expressive can be just ridiculous.