[HN Gopher] How types make hard problems easy
___________________________________________________________________
How types make hard problems easy
Author : tlf
Score : 36 points
Date : 2024-12-19 19:38 UTC (3 hours ago)
(HTM) web link (mayhul.com)
(TXT) w3m dump (mayhul.com)
| tinthedev wrote:
| Not to devalue the author, or their findings/learnings... but I
| could see this was a JavaScript/Typescript coder (very likely
| self-taught) learning about typing paradigms.
|
| A lot of people, especially people from the same background,
| would benefit from branching out and learning some other
| programming languages/paradigms.
|
| Some... statically typed and actually compiled languages. Maybe
| to take an entry course in CS.
|
| It's very popular to hate on formal education, especially in
| software, but all these lessons would have been learned in the
| first semester or two.
| tugu77 wrote:
| 100% this. For a C++ or Rust programmer this reads so weird.
|
| Don't get me wrong, I'm not hating on JS here, and I have lots
| of beef with C++, but I fully agree with your take that TS
| barely scratches the surface of the statically typed world.
| throwuxiytayq wrote:
| Based on my small amount of work done in TS, it seemed like
| one of the more advanced type systems out there. To the
| detriment, even. The language was just huge, and that was
| years ago.
| eyelidlessness wrote:
| And it's so advanced because it was/is designed to
| represent the types of real world dynamic JavaScript. More
| often than not, when people complain about the complexity
| of the types they encounter in the TS type system, they're
| really complaining about the types of the underlying JS
| (which are the same whether they're expressed statically or
| not).
| wk_end wrote:
| There's a cultural problem in the TypeScript ecosystem, I
| find, where people are impressed (with both themselves
| and others) when complex interfaces can be expressed in
| the type system, and tend to embrace that instead of
| settling for simpler (and often admittedly more verbose)
| ones. Maybe that's because they're an ex-JS programmer
| who wants to use the exact same interface they'd use in
| JS with no compromise, or maybe it's just because they
| think it's cool. Either way I think it's really
| detrimental to TypeScript as a whole.
| TheHegemon wrote:
| Do you have some examples for that?
|
| Most cases I've seen with more complex interfaces is due
| to the fact that it is what the interface truly expects.
| Usually making it simpler tends to mean it's actually
| wrong or incomplete.
| FractalHQ wrote:
| This isn't true, is it? I've only ever heard that TypeScript
| has one of the most advanced type systems of any mainstream
| language.. but I don't have enough experience with other
| languages to know how true that is.
| throwuxiytayq wrote:
| In my experience, university is one of the least efficient ways
| to learn CS. The actually useful classes are few and far
| between, dwarfed by useless outdated courses, courses that
| aren't very relevant to the job, and classes that are sadly
| lead by incompetent burnouts who don't know that they're
| teaching, come terribly unprepared, and in general seem to hate
| their job. Most of the people there have _theoretical_
| experience in writing software. But maybe that's just my shitty
| university. I dunno. Supposedly one of the better ones.
| CaptainNegative wrote:
| I think the problem is in going for a Computer Science degree
| when you really meant to study Software Engineering.
| n4r9 wrote:
| I imagine quite a bit of a Computer Science degree _is_
| relevant if you plan to be a computer scientist.
| karaterobot wrote:
| On the other hand, as an Engish Lit major who taught himself
| programming from zero, and worked as a programmer for over a
| decade, _all_ my experience writing software was practical,
| and I don 't think that's the right way to go either. I wish
| I'd had any level of theoretical education that might have
| exposed me to fundamental concepts you ( _with yer fancy
| book-learnin '_) probably take for granted. If someone just
| learns on the job, or just learns as they go, they don't
| learn stuff until they need to. They learn it in a hurry, and
| on a deadline. That's not the best way to get a firm handle
| on tricky subjects, and maybe as a consequence, I always felt
| a couple steps behind my peers.
| thorum wrote:
| I've spent many years working in statically typed languages and
| doing formal study. I expect the author's "inordinate amount of
| time spent working on the Heartbeat codebase, a 300k+ line
| Typescript full-stack application" is a much more powerful
| education.
|
| Actually wrestling with the problems that a thing was made to
| solve, in a real world project, is always a better teacher than
| someone just telling you to use the thing because it's best
| practice.
| tlf wrote:
| That's interesting to hear. I started out with a formal CS
| education learning Java & C in school. I've found that
| traditional CS education doesn't really take this approach. A
| lot of what I was exposed to was very OOP-heavy practices that
| emphasized data modeling via class hierarchy. To me, the
| expressiveness of the Typescript system (being able to do
| things like sum types or branded types) is what unlocked a lot
| of potential despite not being a compiled language.
| motorest wrote:
| > A lot of people, especially people from the same background,
| would benefit from branching out and learning some other
| programming languages/paradigms.
|
| I completely agree. I started reading the article expecting to
| read something interesting or smart about functional
| programming,but it turns out the blogger is just very vocal at
| telling the world their excitement over reinventing the wheel
| and being completely obliovius to what actually represents very
| basic things in any intro to software engineering course.
| t-writescode wrote:
| It's always fun getting to see people experience the positives of
| type systems. So many of the most popular and "easy" / "user-
| friendly" languages drop types in favor of friendliness and
| speed. The most vocally popular web languages - Python, Ruby and
| Javascript - all seem to either ignore or not have types at all.
|
| People make huge projects in them and start learning new
| techniques and then the weight of the choices they made begin to
| grow.
|
| Enter: Types, a frequent savior. Not always the best choice for
| everyone, but a very good and useful thing.
|
| I welcome this person on their journey!
| stavros wrote:
| > The most vocally popular web languages - Python, Ruby and
| Javascript - all seem to either ignore or not have types at
| all.
|
| All three of those languages have ways to use typing, so this
| statement is only true in the sense of types not being
| mandatory, which is also the case in any language that has the
| Any type.
| Barrin92 wrote:
| >Using the same language everywhere. Naturally, if we want to
| share type information as much as possible, we need to be using
| the same language
|
| This goes to the heart of what's not great about this, types
| impose global semantics on a piece of software, they introduce
| coupling. (It's why Alan Kay used to stress "late binding of all
| things") as a feature of managing complexity.
|
| In fact one result of this kind of programming were
| microservices. What do they do? _Reintroduce runtime dynamism_.
| It 's not often framed that way but there's a reason you see more
| statically typed microservices than Lisp or Erlang ones. It's
| because they're an attempt to get away from the coupling imposed
| by type driven programming and towards more independence of each
| service. Which is already baked into message based, dynamic
| languages.
|
| And there's also a fundamental misunderstanding about data and
| types in the article.
|
| > Making our types represent the "truth"
|
| Types can't represent truth. Real world data doesn't have types.
| It changes incrementally however it wants, and all the time. You
| can use types to not let something you don't want into your
| program, but you can never represent arbitrary real world data by
| matching types onto them.
| esafak wrote:
| > Types can't represent truth. Real world data doesn't have
| types. It changes incrementally however it wants, and all the
| time.
|
| What do you mean? If a variable is a date/time or an integer
| etc. in the real world it should stay that way and be
| represented as such in software.
| leeeeeepw wrote:
| AI chatbot example, you're chatting and then there could be
| some Mark down, latex, images maybe base64 encoded webp,
| audio files, we can type all this stuff do all the
| validations and such, understand it better and there's some
| gains to be had doing that, then likely someone like Facebook
| comes along with this Giant byte Transformer expert system
| with all of the data specific optimisations, that's kind of
| the bitter lesson but I guess the main point is that the
| problem itself of how to best communicate with AI is not
| necessarily solved so you can get bogged down typing the best
| possible ways to do it but it's a moving target.
|
| Same with a lot of systems like say a search system that
| tracks data using the best embedding, well we don't know what
| that best embedding is in terms of price performance and
| encoded knowledge perf it's just a moving target.
|
| Send me the system that tracks important metrics effecting
| the stock market, or a weather system etc... the sensors are
| all updating and then an entirely new thing comes along like
| Starlink that helps us track the weather in totally new ways
| msanlop wrote:
| > get bogged down typing the best possible ways to do it
| but it's a moving target
|
| As someone who is still learning this is a huge reason why
| I've come to love dynamic languages. Any project I do
| involves a lot of rewriting as the code evolves, I found
| that trying to predict ahead of time what the structures
| and types is a big waste of time. I've found the best
| middle ground for me to use python with type hints. It
| allows for quick iteration and I can experiment and only
| then update the types to match what I have, so that I can
| still get LSP help and all that.
|
| But I could see this being less relevant with more
| experience
| ervine wrote:
| Not if your types represent something you don't control, like
| an API response.
| Garlef wrote:
| > you can never represent arbitrary real world data by matching
| types onto them.
|
| I think that's why the article references the 'parse, don't
| validate' article: Real world data is messy and so you ingest
| it into your business logic at the system boundaries via
| parsing.
| wryoak wrote:
| The first point lost me because it pushed responsibility for
| functioning software onto the user. If your entire application
| ecosystem has to be recompiled because you conceived of a new
| clever way to conceptualize the data that doesn't actually affect
| the user experience, what happens is I have to update my damn
| bank app every time you think you've done a smart, even though
| you've changed nothing in regards to my checking my balance.
| digging wrote:
| I loved this paragraph:
|
| > This dichotomy gels really well with the way my brain works.
| I'm able to channel short bursts of creative energy into
| precisely mapping the domain or getting type scaffolding set up.
| And then I'm able to sustain long coding sessions to actually
| implement the feature because the scaffolding means I rarely have
| to think too hard.
|
| It's why I keep begging my team, every time there's a new
| codebase (or even a new feature), to stop throwing `any` onto
| everything more complicated than a primitive. _It is exhausting_.
| It forces me to waste energy on the shitty, tedious parts. It
| forces me to _debug working code_ just to find out how it works
| before I can start my work.
|
| They tend to take the quickest solution to everything -- which
| means everyone else has to do _the same work_ over and over again
| until someone (me, invariably) sits down and makes a permanent
| record of it.
|
| In doing this they ensure that _I can 't trust any of their
| code_, which is counterproductive for what should be obvious
| reasons. Every time I work on established, untyped (or poorly
| typed) code, it's like I'm writing new code with hidden, legacy
| dependencies.
| ervine wrote:
| Why is `any` allowed at all? Enable strict mode, set up your
| linter, don't allow any implicit or explicit `any` anywhere.
|
| Without this, Typescript is next to useless. Not knowing if the
| types are good is worse than no types at all.
| phyrex wrote:
| Progressive typing of an untyped code base. Types that are
| too complex to represent in that type system.
| t-writescode wrote:
| * Common functions such as parsing functions in languages
| that don't support function overloading *
| "equals" and other global functions.
| ervine wrote:
| Yep, adopting strict after the fact is a different
| conversation, but one that has been talked about a bunch
| and there is even tooling to support progressive adoption.
|
| Types that are too complex... hmmmm - I'm sure this exists
| in domains other than the bullshit CRUD apps I write. So
| yeah, I guess I don't know what I don't know here. I've
| written some pretty crazy types though, not sure what
| TypeScript is unable to represent.
| mikepurvis wrote:
| Progressive code QA in general is IMO an underexplored
| space. Thankfully linters have now largely given way to
| opinionated formatters (xfmt, black, clang-format) but in
| the olden days I wished there was a way to check in a
| parallel exemptions file that could be periodically
| revised _downward_ but would otherwise function as a line
| in the sand to at least prevent new linter violations.
| umvi wrote:
| Sometimes you don't have the type for something, especially
| if it's 3rd party code. For example, if you are integrating
| recaptcha with your page:
| https://developers.google.com/recaptcha/docs/loading
|
| You could try to craft your own type to match google's schema
| or hunt down 3rd party types, but just doing `(window as
| any)["__grecaptcha_cfg"]` gets the job done much faster and
| it's fairly isolated from the rest of the code so it doesn't
| matter too much.
| ervine wrote:
| Yeah, those are few and far between, generally there will
| be a DefinitelyTyped for anything popular, and you start
| choosing libs that are written in TypeScript over ones that
| aren't.
|
| But for your own handwritten application code, there is no
| excuse to use `any`.
| swatcoder wrote:
| You don't have to provide complete types. If you know what
| you need to access, and what type to expect (you darn well
| should!), you only have to tell TypeScript about those
| specific properties and values.
|
| Generally, the conveniences of allowing any are swamped by
| the mess it accumulates in a typical team.
| digging wrote:
| [delayed]
| digging wrote:
| That's what I would do if I were the project lead, but when
| the most senior developers are the ones who refuse to budge
| and just ignore anyone raising concerns, letting type-fix PRs
| rot for weeks, they disable the rule making `any` an error
| and do what they want. I never said I was in a well-
| functioning team.
| alephxyz wrote:
| >Changing our database schema should cause us to see errors in
| our frontend code.
|
| I shuddered.
| axelthegerman wrote:
| And:
|
| > How types make easy problems hard
|
| Sure that's sometimes an issue with the type system itself
| (looking at you Sorbet) but also preventing the programmer from
| taking advantage of the flexibility, expressiveness and elegance
| the language itself my add (yes, Ruby).
|
| But even Typescript, which is arguably one of the better type
| system/language pairings out there, often causes more headache
| than it's worth.
| umvi wrote:
| I've seen some truly insane TS types. Ones that validate SQL
| queries and stuff.
|
| The problem with complex TS types is that there's no debug
| tooling. You can't set a breakpoint, you can't step through the
| type propagation. If there's an issue you have to just do trial
| and error, which can be very tedious.
|
| Here's a super complex type I ran into in the wild that has a
| bug that is extremely difficult to fix unless you burn hours on
| trial and error: https://github.com/openapi-ts/openapi-
| typescript/blob/main/p...
|
| (the bug in question, still unfixed):
| https://github.com/openapi-ts/openapi-typescript/issues/1769
|
| It was so hard to fix this bug that I found it easier to just
| rewrite the entirety of the library but using code generation
| instead of ultra complex TS types to accomplish the same
| outcome.
| shreddit wrote:
| I also recently switched from javascript to typescript and
| noticed a clear improvement on my speed to write code. Before i
| had to constantly switch between files to check what i exactly
| passed to a function. But I knew C# before so a typed language is
| nothing new for me. But when i started with javascript exactly
| this "untyped" language felt like something good, it felt much
| less of a burden to think about the code beforehand. Now i look
| at dozens of projects which a have to be converted to typescript
| because I simply cannot deal with this typelessness anymore...
| TZubiri wrote:
| Looking forward to the response article on how types can make
| easy problems hard.
| moshegramovsky wrote:
| C++ guy here. I love being able to make a change and watch the
| compiler tell me what's broken. In the past year, I was able to
| justify large scale changes to a big codebase because I could say
| with confidence that the type system would reveal all. And it
| did.
___________________________________________________________________
(page generated 2024-12-19 23:00 UTC)