[HN Gopher] Playing Sudoku in TypeScript while the type checker ...
       ___________________________________________________________________
        
       Playing Sudoku in TypeScript while the type checker highlights
       mistakes
        
       Author : mjcurl
       Score  : 125 points
       Date   : 2024-08-19 21:18 UTC (4 days ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | paradite wrote:
       | Ok can we reduce sudoku to something Turing complete and hence
       | prove TypeScript is Turing complete?
        
         | itishappy wrote:
         | Issue #14833 - TypeScripts Type System is Turing Complete
         | 
         | https://github.com/microsoft/TypeScript/issues/14833
        
           | brap wrote:
           | Does this mean that some types never get resolved? How does
           | the type checker handle that?
        
             | anamexis wrote:
             | Indeed, the link gives an example of such an infinitely
             | recursive type:                   type Foo<T extends
             | "true", B> = { "true": Foo<T, Foo<T, B>> }[T];         let
             | f: Foo<"true", {}> = null!;
             | 
             | As for how it's handled, it yields the error "Type
             | instantiation is excessively deep and possibly infinite.
             | [2589]" I'm not sure what the max stack depth is, though.
        
         | umanwizard wrote:
         | Checking a sudoku board always terminates, so no.
        
       | davidsgk wrote:
       | An amazing (if a bit flowery) read that highlights more arcane
       | stuff you can do with the TS type system: https://www.richard-
       | towers.com/2023/03/11/typescripting-the-...
        
       | a_wild_dandan wrote:
       | Using TypeScript for the entire stack feels like a superpower.
       | The type system is incredible. V8 is fast. The frameworks are
       | phenomenal (Next.js, Material UI, etc). The ecosystem is
       | enormous, with packages for _everything_. The unified codebases
       | save gobs of duplicate code (e.g. ferrying data betwixt client
       | /server). I'm not surprised that such an expressive system can
       | play Sudoku!
        
         | sva_ wrote:
         | > with packages for everything
         | 
         | Which can quickly turn into a crutch if you're not wise about
         | it
        
           | brigadier132 wrote:
           | One thing I do when I see a dependency I want to use is get
           | its github and paste it in this site:
           | 
           | https://codetabs.com/count-loc/count-loc-online.html
           | 
           | Depending on the # of lines of code and how many people use
           | it actively I decide between just
           | 
           | * forking it and using the fork as a dependency
           | 
           | * copying the parts i need from it
           | 
           | * or just using it as a dependency
           | 
           | Either way, the dependencies existing is just a boon. Even if
           | you don't want to depend on it directly you can use the
           | existing work as a guide and implement something yourself.
        
         | leononame wrote:
         | For me, it's the opposite. The type system is decent, but it's
         | generics can get extremely out of hand, it's not sound, and I
         | run into weird type errors with libraries more often than not.
         | 
         | Having no integer types (ok, this isn't something typescript
         | could just implement) other than BigInt is another big one for
         | me.
         | 
         | That you can just do `as unknown as T` is an endless source of
         | pain and sometimes it doesn't help that JS just does whatever
         | it wants with type coercion. I've seen React libraries with
         | number inputs that actually returned string values in their
         | callbacks, but you wouldn't notice this until you tried doing
         | addition and ended up with concatenation. Have fun finding out
         | where your number turned into a string.
         | 
         | The number of times I've read `... does not exist on type
         | undefined` reaches trauma-inducing levels.
         | 
         | TypeScript is as good as it can get for being a superset of JS.
         | But it's not a language I have fun writing stuff in (and I even
         | fear it on the backend). It has its place, and it's definitely
         | a decent language, but I would choose something else for
         | frontend if I could, and wouldn't use it on the backend at all.
         | I somehow don't trust it. I know people write amazing software
         | with it, but YMMV I guess.
        
           | carderne wrote:
           | I tend to agree with you but for problem like this one:
           | 
           | > That you can just do `as unknown as T` is an endless source
           | of pain
           | 
           | You should be using strict typingcheck/linting rules
           | somewhere in your pipeline to make these illegal (or at least
           | carefully scrutinised and documented).
        
             | ridiculous_leke wrote:
             | Those rules should be enabled by default.
        
               | moritzwarhier wrote:
               | ESLint rules that require type information (not just
               | stripping types) are prohibitively expensive for larger
               | code bases.
               | 
               | As far as I know, there isn't any kind of tsconfig rule
               | to disallow this (please correct me if I'm missing
               | something here!). So unless you're using tools I don't
               | know about, this is kind of a mandatory last bastion of
               | "any".
               | 
               | You can disallow any, enable the strictest possible
               | null/undefined checks (including
               | noUncheckedIndexedAccess). And there's also the assertion
               | TS check that normally prevents erroneous type
               | assertions.
               | 
               | But "as unknown as MyType" is not preventable by means of
               | tsc, as far as I know. Unless there's an option I don't
               | know do disable this kind of assertion (or even all
               | assertions).
        
               | lolinder wrote:
               | How large is too large and what counts as prohibitive?
               | We're using lints with types on over a million lines of
               | TypeScript and the lints are instant inside of the
               | editors. They take a good 10 minutes to run in CI across
               | the whole project, but that's shorter than the tests
               | which are running in parallel.
        
             | leononame wrote:
             | Sure, I agree in general, but I've found that:
             | 
             | 1. If someone is willing to do `as unknown as T`, they're
             | probably also just as willing to do `// @ts-ignore`. 2.
             | It's not only your own code, it's the libraries you use as
             | well. Typings can often be slightly incorrect and you have
             | to work around that occasionally.
        
               | mynameisvlad wrote:
               | For #1, this is literally what PRs are for. Someone might
               | be willing to do it, but it should be stopped before
               | merge. If it isn't, you have bigger problems to solve
               | than type coercion.
               | 
               | For #2, if it's open source you're welcome to change the
               | source or its typings.
        
               | cdaringe wrote:
               | Popular libraries tend to get type hygiene issues ironed
               | out rather quickly for 90% of the API surface area. For
               | this reason, i find that lib selection from npm is much
               | easier these days. The heuristic is simple:
               | 
               | 1) has types? 2) has (large) download count? 3) has docs?
               | 
               | After that it's generally smooth sailing. Of course this
               | doesnt at all apply to the application codebase being
               | applied to, but one of the parent/sibling remarks
               | emphasized "madness" and i seek to smooth that over.
               | 
               | Noisy? Yes. Madness? Nah.
        
               | nox101 wrote:
               | You can also turn off all warnings in C and C++ (and
               | C#?). That's not a flaw in the language it's a flaw in
               | code bases and programmers that turn them off.
        
           | tarruda wrote:
           | > Having no integer types (ok, this isn't something
           | typescript could just implement) other than BigInt is another
           | big one for me.
           | 
           | Is that a performance thing? I believe JavaScript VMs can
           | specialize/optimize Numbers and BigInts that only contain
           | valid 32 int values.
        
             | leononame wrote:
             | None of these are performance concerns. Modern JS engines
             | are plenty fast for most of my use cases.
             | 
             | It irks me that I can't trust it to be an integer within a
             | given range. Especially with Number, I often have the
             | sensation that the type system just doesn't have my back.
             | Sure, I can be careful and make sure it's always an
             | integer, I've got 53 bits of integer precision which is
             | plenty. But I've shot myself in the foot too many times,
             | and I hust don't trust it to be an integer even if I know
             | it is.
             | 
             | As for BigInt, I default to it by now and I've not found my
             | performance noticeably worse. But it irks me that I can get
             | a number that's out of range of an actual int32 or int64,
             | especially when doing databases. Will I get tto that point?
             | Probably not, but it's a potential error waiting to be
             | overlooked that could be so easily solved if JS had
             | int32/int64 data types.
        
               | mewpmewp2 wrote:
               | Do you have any more specific examples where it has
               | caused a problem not having int type specifically?
               | 
               | I can't really remember having a problem with it myself,
               | but maybe your usecases are different.
        
               | leononame wrote:
               | Not really. In my parent comment I tried to make clear
               | that it's not a limitation for me in real-world scenarios
               | I encounter, but still something I feel like being a
               | potential class of problems that could be so easily
               | solved.
               | 
               | When I really needed dedicated integer types of a
               | specific size, e.g. for encoding/decoding some binary
               | data, so far I've been successful using something like
               | Uint8Array
        
               | throwanem wrote:
               | Sound currency arithmetic is a lot harder when you have
               | to constantly watch out for the accidental introduction
               | of a fractional part that the type system can't warn you
               | about, and that can never be safe with IEEE 754 floats.
               | (This doesn't just bite in and near finance: go use
               | floating-point math to compute sales tax, you'll find out
               | soon enough what I mean.)
               | 
               | Bigints solve that problem, but can't be natively
               | represented by JSON, so there tends to be a lot of
               | resistance to their use.
        
               | baq wrote:
               | I'm converting a billing system from js to ts right now.
               | 
               | Looking for a therapist.
        
           | a_wild_dandan wrote:
           | You're blaming TypeScript for self-inflicted wounds.
           | 
           | Don't blame the type system that you banished (with `as
           | unknown as T`) for not catching you; or for some React
           | library having bugs, e.g. an incorrect interface; for not
           | defining types and Pikachu-facing when types are `undefined`.
           | These traumas are fixed _by using_ TypeScript, not ignoring
           | it.
        
             | foota wrote:
             | These issues don't exist in languages that aren't built on
             | a marsh.
             | 
             | More specifically though, I feel like the way javascript
             | libraries with types work is often painful to use and
             | that's why people use TS's escape hatches, whereas the same
             | thing doesn't happen in languages where everything is built
             | on types from the get go.
             | 
             | The same friction is true for example of using C libraries
             | from other languages.
        
               | rty32 wrote:
               | "don't exist in languages that aren't built on a marsh"
               | 
               | Sure. Last time I checked, JavaScript is the language
               | that actually powers the web. If you can get a language
               | that isn't built on a marsh along with all the libraries
               | to run the web, I'll switch in a second.
               | 
               | In other words, the criticism is simply irrelevant. If it
               | works, it works. We don't talk about technologies that
               | don't exist.
        
               | skitter wrote:
               | We do in fact talk about technologies that don't exist.
               | Creating new technologies would be rather difficult
               | otherwise.
        
             | leononame wrote:
             | Well, the reality of the situation still is that there are
             | libraries with incorrect or low quality typings that blow
             | up in your face. Me using TypeScript will not make that
             | library better, but this problem is still the daily reality
             | of using TypeScript. It's not the fault of TS, but still a
             | pain you encounter when working with it.
             | 
             | I haven't worked with a language where you can statically
             | cast invalid types that easily since C, a language not
             | exactly famously known for its safety.
             | 
             | There's a reason `as unknown as T` exists, and it's
             | JavaScript's highly dynamic nature and absence of runtime
             | types (ignoring classes and primitives). It's an escape
             | hatch that is needed sometimes. Sure, within your own
             | codebase everything will be fine if you forbid its use, but
             | every library call is an API boundary that you potentially
             | have to check types for. That's just not great DX
        
               | iainmerrick wrote:
               | _I haven 't worked with a language where you can
               | statically cast invalid types that easily since C, a
               | language not exactly famously known for its safety._
               | 
               | But it's not the same situation at all, is it? If you
               | make an invalid cast in C, your program will crash or
               | behave in bizarre ways.
               | 
               | If you make an invalid cast in TS, that doesn't affect
               | the JS code at all. The results will be consistent and
               | perfectly well-defined. (It probably won't do what you
               | wanted, of course, but you can't have everything.)
               | 
               | TS is much more like Java than it is like C (but with a
               | much nicer type system than either).
        
             | iainmerrick wrote:
             | Totally! I really wonder what these libraries people are
             | complaining about that have such bad type definitions. In
             | my experience TS definitions on the average NPM package are
             | generally fairly decent.
        
           | lolinder wrote:
           | > it's not sound
           | 
           | This comes up in every one of these threads and I always
           | wonder: do you actually experience problems with soundness in
           | your regular coding? (Aside from `as unknown`, which as
           | others have noted just means you need a linter to stop the
           | bad practices.)
           | 
           | It feels like such a theoretical issue to me, and I've yet to
           | see anyone cite an example of where it came up in production
           | code. The complaint comes off as being more a general sense
           | of ickiness than a practical concern.
        
         | harha_ wrote:
         | TypeScript is overly complicated and for what? Compile-time
         | "safety". It's better than plain JavaScript, though whatever
         | library I pull as a dependency and peek inside the
         | TypeScript<>JavaScript interface glue, I always find horrors
         | beyond my comprehension.
        
           | mynameisvlad wrote:
           | > the TypeScript<>JavaScript interface glue
           | 
           | ... the typing file? That's literally the only thing that's
           | different and if the original codebase was written in TS then
           | is literally the types they defined.
        
             | harha_ wrote:
             | Well either the typing glue or the library itself if it's
             | written in TypeScript. My point was: the types are too damn
             | complicated. Way too complicated for what they achieve.
             | Almost always.
        
           | xamuel wrote:
           | Compile error messages in a classical typed language: "Error:
           | Object of type 'StructA' cannot be assigned to variable of
           | type 'StructB'"
           | 
           | Compile error messages in TypeScript when you use a library
           | like React: "Error: Cannot reconcile <5 pages of arcane
           | gibberish> with <5 pages of different arcane gibberish>"
        
         | SonOfLilit wrote:
         | While TypeScript seems to be a nice language, it's ecosystem is
         | the JS ecosystem and it is _madness_.
         | 
         | Major versions of some common library breaking backwards
         | compatibility released every week mean you need to run as fast
         | as you can just to stay in place.
         | 
         | Public opinion can't be relied upon. The most popular ORM
         | library just recently added support for native JOINs, and this
         | wasn't common knowledge (I almost used it before at had them!).
         | The most decent ORM as chosen by some coworkers very
         | experienced with the ecosystem still doesn't support subqueries
         | (well, there's an escape hatch for writing them in raw SQL...).
         | Some marketer-turned-programmer created hundreds of useless
         | packages (like, a separate package per ansi color) that all
         | require each other, and they are popular enough that if you'll
         | run npm ls in your real world project you will find that you
         | depend on them.
         | 
         | Having professionally used cargo, pip, even cabal, npm feels
         | like the eternal september of open source packages.
        
           | yieldcrv wrote:
           | yeah this part is pretty bad
           | 
           | you can get lucky and reach a nirvana state where all your
           | dependencies function well in a new project, but 6 months
           | later its a disaster like ah you need to upgrade node, but ah
           | your transpiler requires the older version of node, but ah
           | the semantic versioning was not followed by your type
           | definition addendum library and now there were autoupdated
           | breaking changes, ah your project only worked with a locked
           | package file and if you re-install any package the wrong way
           | everything breaks in incomprehensible ways!
           | 
           | I know my way around it though, so yay big bucks and quick
           | deployment of greenfield projects
        
             | space_crab wrote:
             | I know this isn't realistic for many many scenarios, but if
             | you can help it there is a sweet spot where you dedicate
             | ~30 minutes to merge weekly dependabot updates and you
             | don't run into this problem.
        
           | lolinder wrote:
           | Most of the madness that you're describing there isn't
           | inherent in the JavaScript ecosystem, it's more to do with
           | undisciplined development practices that might be more likely
           | to be enabled by JavaScript's flexibility but are by no means
           | required in order to participate.
           | 
           | Don't use libraries that aren't stable. Aggressively trim
           | dependencies. Lock versions and upgrade intentionally.
           | Ideally, use a company registry to cache what you actually
           | want to be using.
           | 
           | Every ecosystem has its problems, and JS+NPM's are largely
           | that it's too good at making everything too easy, leading to
           | an abundance of naive developers building in a naive way.
           | 
           | On the whole I'll take that over the unnecessary barriers in
           | other ecosystems (don't get me started on pip...), but it
           | definitely requires some discipline to navigate safely.
        
         | __jonas wrote:
         | I had this thought with a personal project but I got lost in a
         | nightmare of configuration between typescript, node, the
         | browser, my bundler etc.
         | 
         | Maybe it's a better time with a framework like Next, which I
         | assume comes with the client / server code sharing part
         | preconfigured, bun looked promising as well to simplify the
         | development setup. But I ended up switching to another language
         | for my backend and I feel pretty good about it.
        
       | samwillis wrote:
       | This is super cool, love these sort of projects.
       | 
       | It's crazy what you can achieve with typescript types, what about
       | inferring sql query results types from a raw sql query string:
       | https://github.com/nikeee/sequelts
        
       | prologist11 wrote:
       | Any sufficiently advanced type system is indistinguishable from
       | Prolog.
        
       ___________________________________________________________________
       (page generated 2024-08-23 23:00 UTC)