Skip to content

Instantly share code, notes, and snippets.

@getify
Last active July 20, 2022 18:26
Show Gist options
  • Save getify/a12804972dce7c7bf8b48d28355eca2a to your computer and use it in GitHub Desktop.
Save getify/a12804972dce7c7bf8b48d28355eca2a to your computer and use it in GitHub Desktop.
describing my motivations for designing TypL instead of using TS/Flow

I am often asked why I don't like a tool like TS (or Flow), and by implication, if I don't like it, the assumption is that I don't want any type aware tooling. That's not true, though.

I have many ideas for what I think type-aware tooling in JS could/should be, and they just happen to diverge significantly enough from TS/Flow that I can't bend into pretzels to fit into that mold.

Instead, I've worked on designing a tool I call TypL that I think addresses my concerns. It's in progress.

Here's my main list of motivations for designing TypL instead of TS/Flow:

  1. I want a system that has both compile-time checking AND run-time checking. TypL's design is to compile away the stuff that it checks at compile time and can verify, and leave in the stuff that it knows needs run-time checking. That way, you don't have to write different sorts of type checking for compile-time and run-time. You get both from one set of typing annotation. It doesn't really seem that TS has any desire or intent to ever go in such a direction. As such, TS will never provide me what I want/need.

  2. I want a completely configurable type system, meaning I want the freedom to decide (in configuration, not disable-ts comments) what sorts of type operations (coercions, comparisons, etc), down to the specific type-vs-type level (and even the specific value level, like null and string "0"), are OK and safe, and which ones I want warnings/errors on. TS has a very minimal set of configurations, and basically relies on you just overriding its strong opinions with disable/ignore comments. This is problematic IMO, because it's a tool that changes how you have to code, rather than being a tool that molds to what you (and your team!) want. I like the ESLint style of tool, where everything is configurable, and you can even write your own plugins/rules if you really want. TypL will be completely configurable, and will be extensible similarly to ESLint. TS doesn't seem like they'll ever even remotely go in that direction, so it's not going to be what I want/need.

  3. I want a type system that focuses on where I think types matter in code. IMO, as a dynamic typing language, the important focus for types should be on the values and the expressions that operate on the values. It's NOT like static languages (Java, C++, etc), where the main focus should be on placing type annotations on containers (like variables, parameters, properties, etc). TypL focuses on annotating values/expressions first, and only secondarily (and OPTIONALLY) are those types then "implied" to the containers. TypL applies its rules against values/expressions first, not against containers. I know TS does checking of values and expressions, but those are more about the containers holding the values (that's where you annotate the types of the values). Take for example var x = 1 / "2"; That operation shows an error in TS for the right-hand side. I however know that it's "safe" because I know the / operator will properly coerce that literal (or that value if it's in a variable) from a string to a number. To get TS to stop complaining, I have to cast that "2" (or variable holding the value) to 2, like +"2" or Number("2"). That's one way of solving it, but it's not my preferred way. In TypL, I have two options: I can either annotate the "2" (or variable holding it) as a number, such as number${"2"}, OR I can just set a configuration to allow that sort of operation to pass the check. TypL puts the power back in my hands instead of assuming that it knows better than I do how my code should be. Again, see point #2 above. TS always focuses on typing of containers, so it's never going to be what I want/need.

  4. It matters a lot to me whether the syntax is valid JS. Here's why: I want to be able to run my code as-is with no build step... for example, while doing rapid dev, and just wanting to refresh a browser and see my code run. TypL code runs as-is, and does all the type checking during run-time. You have the OPTION (again see #2 above) to compile that stuff away by checking it at build time, but you also have the choice to skip build/compile checking. Here's why TS comments don't solve this for me: comments are stripped in most build tools, so they don't exist in a production run-time, and comments have no way for a run-time library to validate them (without doing VERY heavy client-side run-time parsing of code). TypL's code is real JS sitting in the code, so it can run as long as there's a very light-weight (~5k) run-time library included in the project, and it can run in ANY environment (browser, node, etc) without that environment needing to know anything at all about TypL. Even if you could defer/offload TS checking to a later-than-build time, that environment would need all of TS in place to do so, and that's virtually guaranteed to be more heavy than a simple 5kb run-time like TypL's approach. Since TS doesn't seem to care much about these sorts of use-cases, I don't think TS is ever going to be what I want/need. (in fairness, I know TypL's syntax isn't super ideal... it's weird/verbose to use back-tick template literals for annotations. that's unfortunate, but I think it's the price worth paying to get what I want in 1-4).

@jserrao
Copy link

jserrao commented Feb 1, 2022

+1 for run-time type checking. Huge, glaring issue with TS and it gets me often when underlying models shift and break things in prod.

@mahdisoultana
Copy link

oh thank you very much for this article it's really help , and i'm alwayse thinking why i should learn TS if i understand and i work with types JS this is all from you , thank you very much Kyle

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment