[HN Gopher] Show HN: Ezno, a type checker for JavaScript and opt...
       ___________________________________________________________________
        
       Show HN: Ezno, a type checker for JavaScript and optimiser for
       React
        
       Author : kaleidawave
       Score  : 33 points
       Date   : 2022-09-22 16:58 UTC (1 days ago)
        
 (HTM) web link (kaleidawave.github.io)
 (TXT) w3m dump (kaleidawave.github.io)
        
       | pwdisswordfish9 wrote:
       | > VDOM is a virtual representation of the document, actual DOM
       | references the document (e.g. .click() isn't on VDOM structures).
       | 
       | This sentence is unreadable. The superfluous/incorrect use of
       | parens for `.click()`, in combination with this page's style
       | sheet and the way that paragraph wrapped in my browser are all
       | things that didn't help, but eventually I was able to move past
       | it. (It still doesn't make any sense, but I know that part isn't
       | where the weirdness is.) Still unreadable. Bad for something
       | pulled from a written work that's supposed to be a list of
       | definitions you reference.
        
       | nilsbunger wrote:
       | What I'd really like is a tsc that creates code to check types at
       | runtime, like for API boundaries and parsing unknown input. Kind
       | of like a built-in Zod. Maybe it's just an automatic type guard
       | anywhere you have an "as SomeType" or an ignore directive.
        
         | afavour wrote:
         | At some point I used a TS->JSONSchema generator and that worked
         | out pretty great. Obviously it would be greater to be built
         | into the language but I think that's always going to be out of
         | scope of what TS aims to do.
        
           | dtech wrote:
           | Yep, it works pretty well if you combine it with a JSON
           | schema validator and call the validator in a isX(data:
           | unknown): data is X type guard.
        
         | mhermher wrote:
         | I really wanted this in my earlier usage of typescript as well.
         | 
         | But the solution really is to assume `: unknown` at API
         | boundaries and run the values through assertion functions:
         | `isSomeType(x: unknown): asserts x is SomeType`.
         | 
         | After using this sort of pattern, I don't think I would want
         | automatic runtime checks anymore, because creating your own
         | explicitly and calling it explicitly works out not so bad.
        
           | davidzweig wrote:
           | We do it like this: https://imgur.com/a/AdeRncw
           | 
           | Just a simple function (ensureType) that checks primitive
           | types (angle brackets for min length). You reconstruct the
           | object using ensureType, writing it back into itself.
           | EnsureType returns what is passed in, with the corresponding
           | type. Has worked well.
        
           | madeofpalk wrote:
           | You can't actually narrow `unknown` down to a structure yet,
           | as you have no way to test whether `property in unknown` or
           | not.
           | 
           | Well, until this is released!
           | https://github.com/microsoft/TypeScript/pull/50666
        
             | mhermher wrote:
             | yeah. You have to assert an object (`Record<string,
             | unknown>`) type first within your asserter (or array or
             | whatever). We ended up having whole stacks of re-usable
             | assertion functions to be used at these boundaries (re-
             | usable on server side too if you're using node!)
        
         | brundolf wrote:
         | My TypeScript-like language (still a work in progress) does
         | that :)
         | 
         | https://www.brandons.me/blog/bagel-bites-refinement
        
           | hutzlibu wrote:
           | Mine, too. (also work in progress, but not published)
           | 
           | I wonder how many of us there are ...
        
         | eagsalazar2 wrote:
         | This x1000! Type guards are a joke and real runtime type
         | checking could be so easy if they prioritized it. Yes you can
         | use zod but then you have to define your types through zod
         | which isn't as neat.
         | 
         | I actually googled for this just yesterday!
        
         | wk_end wrote:
         | You can use io-ts [0] to define your types, and it'll generate
         | functions to typecheck for you. Syntactically it's a bit gnarly
         | and the documentation isn't great; a first-party solution would
         | definitely be nicer. But it works, and it's amazing that it
         | works.
         | 
         | [0] https://github.com/gcanti/io-ts
        
           | mhermher wrote:
           | It's a neat library, but you end up defining your types in an
           | external (outside of TS) syntax, and you lose a lot of
           | language-server features. Also, last I checked it could not
           | handle generics. But it's been a while.
        
             | wk_end wrote:
             | It's not external to TS. You write your types by passing
             | object literals to the functions that generate the
             | validators; TypeScript then infers shockingly precise
             | types, which can be extracted using TypeScript's type
             | manipulation utilities.
             | 
             | It does support generics [0].
             | 
             | [0] https://github.com/gcanti/io-
             | ts/blob/master/index.md#generic...
        
               | mhermher wrote:
               | Sorry, I meant specifically the "syntax" of your type is
               | not TS. It's those object literal constructions you
               | mention.
        
             | eyelidlessness wrote:
             | You don't lose any language server features, you just
             | access them slightly differently. Each function in io-ts,
             | zod, and other TS libraries like them) are type guards, and
             | have companion utility types to extract the static types
             | from their runtime definitions (with `typeof`). I'm certain
             | that io-ts handles generics (I've used it to do so), albeit
             | again slightly differently, in that you need to define them
             | as generic type guards.
             | 
             | I think the clamor for runtime type checking in TS is
             | partly because type guards and their benefits could be
             | better explained at the language level, and partly that
             | libraries implementing them effectively are mostly aimed at
             | users who already understand those benefits.
             | 
             | You _really don't want_ pervasive runtime type checking,
             | except at API boundaries where data is untyped (i.e. the
             | appropriate type is `unknown`). Type guards are _exactly_
             | designed for that use case. For other cases where the types
             | are well known, runtime type checking is needlessly
             | expensive and redundant.
        
               | mhermher wrote:
               | Agree with all of that, but also, it's been at quite a
               | while since I used it. I'm sure it's improved a lot since
               | then, and my memory might be off as well. I really
               | remember not being able to get it to work with generics.
               | But maybe I didn't read the docs deep enough.
               | 
               | We just do what you describe now, and don't even really
               | want automated type checking. We just write our own
               | assertion functions. The weakness of writing your own is
               | that you have to sort of "manually" upgrade them when
               | there type changes, or they drift and your editor won't
               | tell you about it.
        
               | eyelidlessness wrote:
               | If your editor isn't telling you there's a type error in
               | your guard, that's usually a good sign your guard is too
               | large. Even if you're rolling your own (which seems an
               | odd choice but I'll take it as read that you have
               | reasons), it's a good idea to take inspiration from the
               | prior art. With libraries like zod/io-ts etc, it's harder
               | to end up with a mismatch like you describe than to
               | always have your types and guards in sync, because the
               | guards are built from small composable primitives and the
               | types are derived from them. Larger guards built without
               | that are basically a lot of ceremony around `as Foo`,
               | with all the false sense of safety that implies.
               | 
               | Not trying to dissuade you from rolling your own, mind
               | you. Heck, it's been stalled for a while as I focus on
               | other things, but I'm rolling my own whole library (also
               | for reasons, foremost of which is handling JSON Schema
               | generation and validation at runtime without relying on
               | codegen like other solutions do).
        
         | phpnode wrote:
         | Marc J Schmidt has been working on this for typescript at
         | https://deepkit.io/ and it looks very impressive, and
         | ambitious. I made something similar for Flow a long time ago:
         | https://gajus.github.io/flow-runtime/#/try
        
       | simplify wrote:
       | As a programming language geek, TypeScript is one of the best
       | things to ever happen to the industry. It's finally dispelled the
       | notion that "types == Java == bad/annoying", and shown how
       | powerful and convenient a type system can actually be.
       | 
       | (This is something that's been possible for decades, but it never
       | hit mainstream before as it's hard to implement it well enough to
       | satisfy the silly preferences of us typical programmers :)).
        
         | mhh__ wrote:
         | > industry. It's finally dispelled the notion that "types ==
         | Java == bad/annoying",
         | 
         | Where is this industry and how do I avoid it?
        
           | [deleted]
        
         | the_duke wrote:
         | Typescript has a decent type system, but it is really held back
         | by being "just" a type checker for JS, with all the JS
         | semantics.
         | 
         | The way sum types are done in TS is really awkward.
         | 
         | The type system is unsound.
         | 
         | What's worse is that you never have a guarantee that the types
         | are actually correct at runtime, due to bad third party
         | typings, compiler limitations, use of any, ...
         | 
         | It's still a lot better than using plain JS, and a lot of the
         | limitations aren't by choice, but come from the need to compile
         | down to and remain compatible with plain JS.
         | 
         | It just could be so much better.
        
           | staticassertion wrote:
           | I agree with your point that TS is held back by being "just"
           | a type checker. In particular, in Rust I can write code like
           | this:                   let _: Result<Vec<_>, _> =
           | some_iter.collect();
           | 
           | or like this:                   let _: Vec<Result<_, _>> =
           | some_iter.collect();
           | 
           | The only thing that has changed here is the type annotation.
           | Both will compile, but the implementation of `collect` is
           | determined _by_ that type. As far as I know this isn 't the
           | case in typescript, although please tell me if I'm wrong, I
           | have limited experience from it and I'm thinking more from
           | mypy perspective.
           | 
           | This ends up meaning that my types don't _drive_ the program
           | as much. There 's this sort of declarative "here's the thing
           | I want, use an implementation of that method to give it to
           | me" that feels very powerful. I miss this a lot with mypy, my
           | type annotations feel very much like annotations, they are a
           | separate part of my program.
           | 
           | If TS were to lean into itself as its own thing, not just a
           | way to do better JS, I think that'd be amazing. I'd love to
           | see an AOT compiled TS where types are a semantic part of the
           | program, I'd love to see it drop `any` entirely as well, and
           | drop support for using JS in TS.
           | 
           | As for soundness, don't care too much tbh.
        
             | alpaca128 wrote:
             | Another annoying part of this is how every function
             | declaration effectively doubles the list of parameters,
             | once as type signature and once in the usual JS function
             | syntax. And those don't even have to match, neither in
             | length nor name of the parameters.
        
           | Tade0 wrote:
           | > The type system is unsound.
           | 
           | I've never seen this as a barrier to producing working
           | software.
           | 
           | Meanwhile Dart is sound, bit but doesn't have nearly the same
           | adoption.
        
           | enlyth wrote:
           | I wish Microsoft would make a language almost exactly like
           | Typescript, but where code has to be strictly typed (no any,
           | unknown, etc.) and it would compile to a normal binary, with
           | some sort of GC, for multiple platforms.
           | 
           | It would hit the sweet spot for me, I know Rust is popular
           | these days, but it seems like it's made for type astronauts,
           | and sometimes I just want to write some code and get things
           | done quickly and don't care about squeezing out every last
           | drop of bare metal performance or abstracting seven layers of
           | types to please a borrow checker.
        
             | lioeters wrote:
             | I suppose AssemblyScript fits some of those points: no any
             | or unknown; compiles to a binary; GC; cross-platform.
        
             | math_dandy wrote:
             | How about F#?
        
       | fbn79 wrote:
       | Remind me of Hegel (https://hegel.js.org/) but with typescript
       | compatibility. It's a pity Hegel develompent stopped because war
       | in Ukraine (https://github.com/JSMonk/hegel/issues/363). Looks
       | really cool but in my opinion would better to concetrate on type
       | checking living other things (vdom, ssr) out or in optional
       | plugins
        
         | Vinnl wrote:
         | As far as I can see they _are_ living in optional plugins
         | (tentatively called  "framework"), if I understand the post
         | correctly.
        
           | fbn79 wrote:
           | You r right. I missed that point. Cool
        
       | bin_bash wrote:
       | anyone else think it's really strange this is "Ezno" and not
       | "Enzo"?
        
         | barnabask wrote:
         | I didn't realize it wasn't Enzo until reading your comment just
         | now, and that's after skimming the article for several minutes.
         | Now I'm wondering if I'm dyslexic or what.
        
           | user3939382 wrote:
           | It's just a side effect of how we read
           | https://i.imgur.com/o5zL6Rh.png
        
       | juancampa wrote:
       | On a related note: Is there anyone working on a faster tsc? I
       | know there's esbuild and swc, but those only transpile, they
       | don't type-check.
        
         | WorldMaker wrote:
         | Based on the release notes, the Typescript team is working on
         | faster type-checking as continuous goal and has many big long-
         | term irons in that fire. Though a lot of the more recent work
         | has gotten into the performance of projects already scaled into
         | project references and incremental builds, so it may not yet be
         | _obvious_ how much work has gone into performance if you
         | consider your projects small /medium-sized.
         | 
         | It can sometimes be quite an effort to refactor a medium sized
         | project into project references with incremental builds and
         | there's currently no obvious moment where Typescript knows to
         | tell you "you've got a 'large' project now, if you split this
         | workspace into multiple tsconfig projects that smartly
         | reference each other and switched to incremental build flags
         | you'd get a bunch of performance improvements". So that's still
         | a matter of figuring it out for your own projects if you can
         | take advantage of that (and how you would take advantage of
         | that).
        
         | martpie wrote:
         | Rome (written in Rust) is trying to be a faster tsc (amongst
         | other things, like a faster webpack, babel, prettier, etc)
         | 
         | https://rome.tools/#development-status
        
           | e1g wrote:
           | Rome's journey is effectively over - the founders couldn't
           | make it work after raising a VC round, and I wouldn't expect
           | it to go GA.
        
             | dsmmcken wrote:
             | The repo still looks pretty active, which seems contrary to
             | your statement.
        
               | e1g wrote:
               | If you're looking for evidence in the public repo,
               | consider what's not in there: one co-founder is missing,
               | and so are the commits from the other author/co-founder
               | for over a year. Not the signals you want in a dev-
               | tooling project.
        
               | pohl wrote:
               | Or you could look to see if new work is being released.
               | Most recent one was just 17 days ago.
               | 
               | https://twitter.com/rometools/status/1567169157891776514
        
               | lazlo_kovacs wrote:
               | Except how many users do they have? If I were a VC fund
               | looking to give them another round, I'd want to know
               | their metrics, whether that's users, downloads, or
               | revenue. Judging by their blog, it's been a year since
               | they raised the money. Have they produced anything other
               | than a bunch of code? Because code isn't worth much
               | without users.
        
               | ricardobeat wrote:
               | I found it interesting that a good chunk of outside
               | contributions[1] happened before funding, and have almost
               | completely stopped.
               | 
               | [1] https://github.com/rome/tools/graphs/contributors
        
             | jquery_dev wrote:
             | What do you mean by "make it work"? They've raised 4.5M
             | last year, did they just burn through that?
        
               | lazlo_kovacs wrote:
               | It appears from their repo that they have 5-6 people
               | working full time on this. Assuming about 250k per
               | developer that puts their burn at 6 * 250k = 1.5 million
               | a year. So yeah they have some time. Although I would be
               | severely concerned at their progress considering it's
               | already been a year and they don't seem to have shipped
               | much. No proof of PMF or any sort of revenue with over a
               | third of their runway depleted should have them hustling
               | to get on the boards.
        
           | [deleted]
        
         | kidfiji wrote:
         | Yep! The person who started swc is doing just that:
         | 
         | https://kdy1.dev/posts/2022/1/tsc-go
        
         | zamalek wrote:
         | We also need a faster language server. Inference (e.g.[1]) is
         | one of the greatest features of TS, but we're told not to use
         | it.
         | 
         | [1]: https://trpc.io/
        
         | Vinnl wrote:
         | It was just an experiment, but this person was (and is still
         | doing related stuff):
         | https://twitter.com/MarcJSchmidt/status/1551961839394865152
         | 
         | (and an example:
         | https://twitter.com/MarcJSchmidt/status/1552781654065905664)
        
       | [deleted]
        
       | madeofpalk wrote:
       | > Ezno's type checker is built from scratch. Getting the features
       | I wanted requires a lot of different functionality and needed
       | several new ideas that as far as I know aren't present in any
       | type-system or existing checkers.
       | 
       | I would disagree this is a _TypeScript_ compiler. It 's a mostly-
       | typescript-compatible compiler/type-checker.
       | 
       | The Typescript team iterate on it reasonably quickly. If you fall
       | behind as the Typescript team adds new features, and you cannot
       | check that code, is it still "Typescript"?
        
         | anamexis wrote:
         | The author himself does not call it a TypeScript compiler.
        
           | madeofpalk wrote:
           | That is actually completely fair - I still had OP's
           | editorialized headline in mind when reading the site, and
           | didn't notice all it says about typescript is "The checker is
           | fully compatible with TypeScript type annotations" which is
           | probably fair!
        
       | nexxel wrote:
       | Looks really cool!
        
       | brundolf wrote:
       | > One of the key ideas with Ezno is that it attempts "maximum"
       | knowledge of a source
       | 
       | I've been working on a new TypeScript-like language myself from
       | scratch, which among other things takes this approach. Mine can
       | do some of the numeric stuff shown here, but I'm jealous of
       | (inspired by? :)) some of the crazier stuff going on here, like
       | usage-based argument types and tracing not just value _shapes_
       | but value _reference identities_
       | 
       | The "automatic generics" feature in particular is absolutely
       | bonkers. It never even occurred to me that you could do that. I'm
       | wondering if there are unforeseen edge-cases, but also wishing I
       | had it at work. Clunky generics syntax is one of the worst parts
       | of TypeScript, even while generic function types are one of its
       | best parts.
       | 
       | Wow, and side-effects-tracking too! Amazing
       | 
       | I am curious whether some of these checks will be limited by
       | JavaScript's dynamism. Part of why I'm doing mine as a new
       | language is that JavaScript's semantics are just way too flexible
       | to form some of the guarantees I feel like you need for some of
       | this aggressive inference. But now I'm questioning that.
       | 
       | Either way, this is insanely impressive. Definitely not just yet-
       | another-JavaScript-toolchian.
        
         | julesnp wrote:
         | The automatic generics look at lot like how OCaml implements
         | inference for structural typing.
        
         | the_duke wrote:
         | As the sibling comment mentioned, both Ocaml and Haskell use
         | this kind of type inference.
         | 
         | Search for Hindley Milliner type system.
        
           | wk_end wrote:
           | This is far beyond Hindley-Milner (as are Ocaml and Haskell),
           | which is pretty primitive in-and-of-itself.
        
       | mrpf1ster wrote:
       | This looks incredible, looking forward to an official release to
       | play around with!
        
       | [deleted]
        
       | bryzaguy wrote:
       | Wow! Amazing! Am I reading correctly that Ezno is aiming to
       | render React obsolete?
        
         | eyelidlessness wrote:
         | My understanding reading it is that it's implementing something
         | more like SolidJS (which is also a no-VDOM reactive library
         | which looks a lot like React) and Qwik (which also
         | serializes/resumes from state in the DOM), but built into the
         | core compiler rather than as a separate library/JSX transform.
         | I doubt it'll make React _obsolete_ , especially as React
         | expands in scope (e.g. Server Components), but it might be a
         | good replacement for a lot of use cases. It's certainly got my
         | attention!
        
       | immigrantheart wrote:
       | All of these compiler/transpiler related projects, especially for
       | big mainstream language like TypeScript seems like a full time
       | job, more so than any other open source initiatives. You need to
       | keep up with the spec, constantly read the source codes, etc.
       | Kudos to those who are providing their time to do this.
        
       ___________________________________________________________________
       (page generated 2022-09-23 23:00 UTC)