Type Safety with Native JavaScript

(mmikowski.github.io)

35 points | by charlysl 1424 days ago

8 comments

  • CraftThatBlock 1424 days ago
    This is type-safety, but not type-checking. The 2 are entirely different problems, and can complement each other.

    I don't see this being adapted for any project since it doesn't provide any real benefit over using something like TypeScript, which won't let you do these types of mistakes.

    Do you want to handle the errors (this) or not have errors (TS)? Pretty easy answer on my end.

  • HugoDaniel 1424 days ago
    a common misconception is that TypeScript[TS] will provide runtime safety; it won't unless you specifically add functions for it, like the type casts presented in the article.

    The typecast approach presented in the article can be combined with TS to provide runtime type safety; They are not entirely opposite/alternative approaches but complementary.

    • depmann 1424 days ago
      Yes, TS and typecasting can live well together. However, once you combine sensible naming by type and typecasting together, the benefits of TS fade. Then one has to ask: are the remaining benefits worth the expense of running a full TS transpiling infrastructure? In my case, the answer is a definitive 'no'. Typecasting along with Webstorm introspection virtually eliminate may of the issues that TS was designed to solve.
      • wereHamster 1424 days ago
        For most of my day-to-day projects, there is no TS transpiling happening at all, .ts/.tsx files are supported by many toolchains in the very same way .jsx files are supported (without any additional overhead over the regular transpiling that is required for any modern JS project). TypeScript is really only active within my editor, not during bundling. This gives me reliable intellisense, code completion, jump-to-definition, rename-symbol, and other IDE features across the whole project.

        > Typecasting along with Webstorm introspection virtually eliminate may of the issues that TS was designed to solve.

        I personally don't want to stop at /virtually/ eliminating issues that arise due to type errors. I want to /reliably/ eliminate them. And the only way to eliminate type errors is to run a static type checker over the project. (I know the TS type system is not 100% sound, but most definitely better than manual typecasting at runtime).

    • williamdclt 1424 days ago
      There's a library called runtypes (https://github.com/pelotom/runtypes) that integrates TS and Typecasting quite nicely
  • depmann 1424 days ago
    Hi, Author of the Article here :)

    I do not recommend JSDoc. Instead, typecasting has these advantages:

    1. Precise self documenting 2. Much easier to maintain and less verbose (see 1) 3. Requires no external tooling outside of the typecast functions which are hundreds of times less complex than JSDoc checking environments like Closure 4. Adds valuable run-time capabilities that JSDoc does not

    Sincerely, Mike

    • smt88 1424 days ago
      > One approach involves using libraries or frameworks such as Flow or TypeScript that require transpiling or otherwise prepocessing the code.

      This is a crucial premise of your article, and it's untrue. TypeScript[1] and Flow[2] both support using their static typing without transpiling anything (i.e. the full power of the type systems in plain JS files).

      As far as type-cast functions, I've never found that I needed them after switching to TypeScript because the compiler checks that for me.

      If you use type guards on all un-typed input (JSON requests/responses, for example), then you don't need type casting at all because you always know your variable's type. That's the whole point of static typing.

      1. https://www.typescriptlang.org/docs/handbook/type-checking-j...

      2. https://flow.org/en/docs/usage/

      • depmann 1421 days ago
        This premise is factually true for both TypeScript and Flow. Please explain how you could come to any other conclusion.

        I researched this 4 years ago, and since then Typescript has added the `--checkJs` option, but it still you to run a separate process to run the check, which seems to certainly fall under the category of "... otherwise preprocessing the code". And that's an edge case. If you've got TS installed, your almost certainly transpiling. Type guards are typecasting, just renamed to make you sound smarter.

        Flow requires a transpiler (https://flow.org/en/docs/install/) and advocates the use of background process. Again, this solidly fits the above premise.

        These are enormously complex solution to a problem that can be resolved without transpiling by using 6 small functions and a sensible naming convention. Certainly there are many cases where that makes a lot of sense.

        I've developed lots of mission-critical JS that is very widely distributed and there are no type errors despite not using Flow or TS.

      • millstone 1424 days ago
        It's JavaScript; you can't really know.

            Math.round = () => "haha";
        
        Now `Math.round(3)` is a string.
        • SahAssar 1423 days ago
          No, when TS checks js it will check types for built-ins too:

              npm i typescript
              echo 'Math.round = () => "haha";' > test.js
              ./node_modules/.bin/tsc --allowJs --checkJs --noEmit test.js
          
          And you get:

              test.js:1:20 - error TS2322: Type 'string' is not assignable to type 'number'.
          
              1 Math.round = () => "haha";
                                  ~~~~~~
          
              node_modules/typescript/lib/lib.es5.d.ts:708:5
                  708     round(x: number): number;
                          ~~~~~~~~~~~~~~~~~~~~~~~~~
                  The expected type comes from the return type of this signature.
          
          
              Found 1 error.
    • timw4mail 1424 days ago
      Here are some reasons I like JSDoc:

      * The syntax is fairly widespread

      * Documentation pages can be generated from the comment blocks

      * You can use as little or as much as you like

      * Still readable without external tools

      * Uses block comment syntax

      I would generally advocate for a mix of JSDoc for public documentation, and type-checking/type-casting functions for actual runtime checks.

  • wjmao88 1424 days ago
    Data from unknown sources should just be thoroughly checked where they enter js land to make sure they conform to type expectations. If they are, then relying on static type checking from that point on should be fine.
  • blackrock 1424 days ago
    JavaScript is such a terribly designed programming language. But it doesn’t seem like anything will ever replace it. And newer tools, just get built on top of it, and transpiled down to JavaScript, thus adding evermore to be cruft of the language.
    • pathartl 1424 days ago
      I'm a JS/PHP dev turned C# dev and I really just hate having to touch JS these days. For some internal systems we've needed to do some JS to customize Microsoft's Dynamics 365 platform. I opted to write everything in C# and transpile down to JS via Bridge.NET.

      It results in a multi-megabyte JS file, but you know what? My code is clean and organized. I can make use of things like reflection and OOP. I'm honestly very hopeful for Blazor and the future of front end development that isn't so reliant on a language that was really not designed with its current scale in mind.

  • f00_ 1424 days ago
    maybe just JSDoc instead? It's an old standard, widely supported by IDEs, and use typescript for CI/CD

    https://www.typescriptlang.org/docs/handbook/type-checking-j...

  • ptx 1423 days ago
    This appears to propose what is essentially Hungarian notation[1] - and not Apps Hungarian but rather the less useful Systems Hungarian. Since the merits of these ideas have already been discussed extensively over many decades, it seems odd for the article not to make a mention of it.

    [1] https://en.m.wikipedia.org/wiki/Hungarian_notation

    • depmann 1421 days ago
      1. You are applying the ad-hominem fallacy: calling something a name something doesn't remove its value. The reason I didn't point to this label is to avoid people applying the same fallacy and tuning out before considering the merits of the solution.

      2. This is the App-style notation. Notice how 'count' is used to indicate quantity not 'int'. You can see all app-style suffixes listed in the article.

      3. I'm not the only one to come to these conclusions. From the Wikipedia article you provided:

      * Steve McConnell: "... the basic idea of standardizing on terse, precise abbreviations continues to have value. Standardized prefixes allow you to check types accurately ..."

      * Bjarne Stroustrup: "... a technique that can be useful in untyped languages ... [like JS]"

      * Joel Spolsky: "... There's still a tremendous amount of value to Apps Hungarian, in that it increases collocation in code, which makes the code easier to read, write, debug and maintain, and, most importantly, it makes wrong code look wrong..."

      4. this is a sensible, simple, and very light-weight approach to resolve a real problem that is especially pronounced with JS. It has been use for over a decade to manage code and teams and it works very well.

      What naming convention do you instead suggest for JS?

  • WhitneyLand 1424 days ago
    It’s interesting to think about and tinker with maybe, but I don’t see the merit to using this for real life projects.

    In fact I’d recommend against it, considering the better alternatives and the fact that this is yet another thing that can break and has to be maintained.

    I often hear people argue that XYZ is simple so it’s no big deal to use it. But the reality is that code changes hands often and every person who touches code incurs the extra bit of cognitive load.

    Just use Typescript.

    • depmann 1421 days ago
      I would make the exact same argument but with completely the opposite conclusion. Just use type casting which is self documenting and easily maintained. How can using Typescript be considered somehow less complex?
      • WhitneyLand 1417 days ago
        I think there’s more to it than this but let’s pursue your point for a moment. What you’re not taking into consideration is that de facto standards matter.

        What if you invented a language tomorrow called XYZ and it was 20% better than a popular language today?

        Would you language eventually take over and become popular? Maybe. After how many years? Who knows. But until that happens far more JS developers are de facto making an investment in learning at least the basics of typescript vs your mechanism.

        The practical reality of that is if I start putting together a team to build something it’s much less likely that people will have to take time to learn typescript basics then they will to learn your tool.

        Are there times to throw out the old and go with what’s better or simpler? Sure. But that equation is not as simple as X > Y even if that were the case which I’m not convinced it is.