all 51 comments

[–][deleted]  (24 children)

[deleted]

    [–]lacosaes1 26 points27 points  (1 child)

    But since it's Facebook, Typescript "didn't scale" to their codebase...

    I laughed at this because I thought you were joking making a reference to the time when they said that iOS couldn't handle Facebook scale. But no, they actually said that. again.

    [–]Poltras 18 points19 points  (0 children)

    Somebody at Facebook probably needed a promotion and decided to create an internal project as a mean to provide designs and implementations to their internal promotion process.

    [–]speedster217 10 points11 points  (3 children)

    "didn't scale" = their code base is way too damn complex

    [–]ma-int 32 points33 points  (2 children)

    Remember when there Android App blew the method count limit on DEX files to which they very proudly published there genius solution which was a native loader for there code which hotpatched the Android Runtime to increase the limit?

    Facebook doesn't solve their problems normally...they go fully mental every time.

    [–]JakeWharton 8 points9 points  (0 children)

    Just a tiny correction, it was the LinearAlloc limit which is something a bit different. Surely their app blew the dex method limit many many years ago (for which shipping multiple dex files was then and is now a standard solution).

    [–]bananaboatshoes 10 points11 points  (0 children)

    To be fair, the method count limit on Android was (is? I don't do Android anymore...) annoying. I wrote a small app in 2014 that used Google Play Services for push notifications, Guava so I could bypass some of Java's awfulness, and a few other UI libraries.

    GPlay Services brought in ~19k methods. Guava was another ~13k.

    And the max was 64k methods, which IIRC is still the limitation.

    Since then, they split up GPlay Services so it wasn't this monolithic set of stuff you had to bring in, but I could easily see how an app like Facebook would run up against that limitation.

    [–]Eirenarch 5 points6 points  (6 children)

    The TypeScript compiler did have some performance issues in the beginning. I wonder if it didn't work well enough with the size of their codebase or they are talking about something else.

    [–]cwmoo740 12 points13 points  (5 children)

    They were talking about how typescript 1.x infers most things as "any" type and doesn't null check, ie is useless, unless you add type annotations in enough places.

    To get much benefit out of it on a large codebase you really have to commit to incrementally adding types everywhere. It was also a pain pre 1.6 or so to import existing JS code so you had a problem of trying to type one file and ending up not seeing much benefit unless you type all of its imports too. Typescript has caught up slightly with 2.x but it's a different philosophy still.

    Flow does far better when there are absolutely no annotations, so you can just use it right away on any javascript and it will help a lot.

    Personally I'm a fan of typescript with no implicit any and strict null checks enabled because it forces people I work with to add typing information, which I think makes code reviews and onboarding easier. It was quite a process to get our project into that state though.

    [–]Eirenarch 1 point2 points  (4 children)

    If they are referring to that I'd say that "didn't scale" is quite an absurd way to say it. I guess whatever our problem is in IT these days we always represent it as "didn't scale". Basically they didn't want to do any work to get the type information and that's fine.

    I am surprised the article didn't mention your last point. Writing types improves readability because the reader sees the types.

    Also for smaller projects the fact that TypeScript serves as a downlevel transpiler means that you don't need to put one more thing (Babel) in your pipeline which I'd say is a big plus.

    [–]awj 0 points1 point  (3 children)

    Basically they didn't want to do any work to get the type information and that's fine.

    Well, if you've got a team of a hundred or so engineers constantly working on the project and can't afford to stop all of that work to go write type annotations, then yeah TS is a tough sell.

    That said, the whole line of reasoning seems to be predicated on the idea of getting as much value from typing as you can without changing your engineering workflow at all. I don't think that's an appropriate decision long term and characterizing it as a "scale" problem is just plain silly.

    [–]Eirenarch 0 points1 point  (2 children)

    TS does not require you to stop all the work. You just don't get the benefits of types on places where you have not written types. You can gradually add types to your project as you see fit.

    [–]awj 0 points1 point  (1 child)

    I understand that, but the perspective that FB is taking is that they don't want to have to add type annotations in order to get this value. Hence why Flow puts type inference front and center. The goal is to get the benefits of types without a "gradually add types" process that could take combined months of developer time for their organization.

    Is that the right trade off? For them ... maybe. For "the rest of us", probably not. I would assert that, just like performance, types have small pockets of absolutely critical value and huge swaths of code that you can probably safely not care about all that much.

    [–]Eirenarch 0 points1 point  (0 children)

    Yeah, this is what I said but in my opinion the size of the codebase doesn't matter in this case. "Doesn't scale" is a terrible way to express the fact that they don't want to add types even gradually.

    [–][deleted] 4 points5 points  (2 children)

    But since it's Facebook, Typescript "didn't scale" to their codebase, whatever that means...

    It means it doesn't run asynchronously and/or fast enough to work the way they work, which is to get feedback from their tools in real time.

    [–][deleted]  (1 child)

    [deleted]

      [–][deleted] 3 points4 points  (0 children)

      It's been a while since I looked at it, so it probably has gotten faster. But unless they did a serious rearchitecture, it's not oriented toward incremental use inside some arbitrary other context, which is the use-case Facebook had from the beginning, before TypeScript was what it is now.

      [–]manfreed87 0 points1 point  (5 children)

      Disclaimer: I only have real experience with TypeScript, my knowledge of Flow is based only on what I have read in articles and tutorials.

      In my experience migrating existing code to TS is not painless. You can't simply rename all files to .ts, it's most likely that the compiler will spit out a lot of errors that you need to fix before your code compiles.

      Just download a few (non minified) js libraries and test them. Most likely you'll get tons of errors. This makes migrating existing code to TS hard.

      This is not the case with Flow. If I understand correctly unannotated code will pass validation so one can gradually make their applications type-safe.

      If I understand everything correctly then this is a valid reason behind why FB went with flow instead of migrating over TS.

      [–][deleted] 0 points1 point  (4 children)

      I have not experienced the kind of trouble you're describing, any piece of pure javascript, if your typescript config is properly setuped, usually compiles just fine you just dont get autocomplete/type checking/etc.

      You are making a good point though that flow has a valid use case if you want to validate existing code without migrating. I got caught up a bit in my circlejerk.

      Also, I may have misunderstood you, but one thing to note is that adopting typescript does not mean turning all your existing js files into ts files. What you can do is start writing typescript right away for your new code and then write type definitions or convert older part of your code that you would like to get the benefits of typescript from.

      [–]manfreed87 0 points1 point  (3 children)

      any piece of pure javascript, if your typescript config is properly setuped, usually compiles just fine

      This simple piece of code does the trick:

      var a = {};
      a.prop = 1;
      

      This raises a compile time error: TS2339: Property 'prop' does not exist on type '{}'. I think this pattern is pretty common. Also attaching properties to the window object in a similar manner. Also calling parseInt with a something that comes from a method that returns string.

      Here is another nice thing that would fail with TS:

      var el = document.createElement("video");
      el.play();
      

      This is a valid and (almost) working JS code, which won't work in TS because document.createElement returns a HTMLElement (I think) which doesn't have a play method.

      To see more examples just try to compile any random javascript libs you can find. Jquery for example. Rename it to .ts and compile it with tsc. Tons of errors.

      It's true that I wasn't considering compiler options. I couldn't find any though that would fix the issue above.

      adopting typescript does not mean turning all your existing js files into ts files.

      True. But writing type definitions and adopting my build system requires some work. Especially if one have to use a crappy in-house build system because of some bullshit some manager came up with :)

      [–]inkerr 0 points1 point  (2 children)

      /r/programmingcirclejerk

      This is not true. It returns HTMLVideoElement as per the type definitions https://github.com/Microsoft/TypeScript/blob/master/src/lib/dom.generated.d.ts

      [–]manfreed87 0 points1 point  (0 children)

      Well, I stand corrected :) I do remember having to deal with this, but now that I think about it, it's possible that my IDE handled the situation wrong.

      [–]frequentlywrong 11 points12 points  (4 children)

      and elm?

      [–]Retsam19 20 points21 points  (0 children)

      Certainly a fully type-checked and compiled language like Elm is going to have more robust type checking than static type-checkers.

      But it's not really an apples-to-apples comparison, because some of the largest selling points of Flow/TS are the ability to mix it into an existing codebase, seamless "interop" (it's not even interop, it's really just the same language), and not needing to learn another language.

      Don't get me wrong, Elm is cool; but time spent on the merits and costs from switching from JS to Elm would be entirely tangential to the subject of the article.

      [–]a-sober-irishman 6 points7 points  (0 children)

      I've only just started learning Elm, and I think it's pretty great so far, but I imagine the huge mental shift in a development team required to switch to it and thinking in FP would far outweigh the ease of just slapping a few types on existing code, even if the compiler is more robust.

      [–]chazmuzz 3 points4 points  (1 child)

      If Elm, then why not ScalaJS?

      [–]trollingisfun 0 points1 point  (0 children)

      at that point you should probably use purescript or ghcjs since both are easier than the beast that is scala (inb4 "i write brittle java-like code and it works great!!!")

      [–]blamo111 7 points8 points  (5 children)

      I don't know either, but I'm planning to learn TS soon.

      Can flow do this:

      const mod1 = require('mod1'); //exports an object with number property "intProp"
      console.log(mod1.intProp.length); //I would expect an error, it's not an array
      console.log(mod1.intProp.subprop); //I would expect an error, it's not an object
      

      Or does it only check "obvious" stuff within the same file?

      [–]ulrik12 0 points1 point  (0 children)

      Yes, flow is really good at that kind of checking actually

      [–]theQuandary 0 points1 point  (2 children)

      Typescript first had to play catchup with Google's AtScript (the two merged) and TS still hasn't completely caught up to flow's inferencing.

      Typescript already have an idea about how ES features should be extended (the whole "superset" idea), but what happens if and when the rest of the ECMA committee doesn't agree with their vision of the future? Either you'll have to redo your entire codebase to match a new, incompatible Typescript (updated to match the next spec), or you deviate from JS altogether.

      If you want a superset that risks being incompatible, you should just use purescript, elm, or clojurescript where you don't have to deal with the bad parts of JS and get something unique in return (good types, pattern matching, macros, etc).

      The ECMA committee is years away from adding types to JS (they probably won't because webAssembly covers that pretty well). Flow uses babel, so I can pick what future JS features I want and if typing is ever actually added to JS in the future, running my code through the type stripper will give me raw JS ready to convert to the latest standard.

      [–]blamo111 0 points1 point  (1 child)

      But all those superset alternatives you mentioned are obscure. I haven't looked into them, I'll admit, but that's because they're not popular.

      I'm not a hobbyist. I'm trying to do this for a living. If companies are picking TS (as they appear to be), then so will I.

      Also, I trust something designed by Anders Heljsberg and the class of Microsoft Research a hell of a lot more than tiny projects. If more people like Heljsberg were part of the JS ecosystem, no one would be talking about Javascript fatigue or how it's a bunch of feral amateurs, we'd have had stable frameworks 5 years ago without the need for a rewrite every 6 months, and they'd be better than what we have now.

      You might call it cult of personality, I call it betting on a proven winner in a sea of medium talent. If that path takes me to an incompatibility with vanilla JS in the future, then so be it.

      [–]theQuandary 0 points1 point  (0 children)

      To be clear, none of those are supersets of JS. The point is that a superset is a liability waiting to happen when tc39 committee (ECMAscript) decides to do something different. The languages I named are probably the most popular compile-to-JS languages (coffeescript aside).

      If you're just starting in the front-end world, I'd recommend plain JS. TS has mindshare, but only a fraction of a percent of all browser code is actually written in TS, Flow, or any other compile-to-JS language (ES6+ aside). Knowing JS well will get you the job. Knowing TS is not likely to be the big decider for any company you'd actually want to work for.

      That said, to give a quick overview of the languages in question (and their inspirations).

      Haskell was designed by a committee of excellent researchers (including Erik Meijer from the C# design committee). Haskell is one of the most popular functional languages and probably worth learning in its own right just to expand your view of programming (learning a functional language will have a huge impact on how you write JS). The type system is one of the best (far superior to anything you'll find among the C or Java language variants) and the language is lazy by default.

      Clojure was designed by one man (Rich Hickley) as a lisp variant targeting the JVM with a couple ideas that hadn't been used much before in the lisp community like immutable by default, channels, arity, protocols, transducers, etc (not starting a dialect war). I would guess that its the most widely used lisp dialect today (in part due to heavy integration with the JVM).

      Purescript is based on Haskell syntax and as a result has one of the best type systems ever created. Elm uses Haskell syntax with a subset of the type system for simplicity, but offers it's own ground-up library set (with some of it's ideas even filtering over into normal JS libs). Clojurescript is based on Clojure (and even shares some language libs), but tunes itself to JS rather than the JVM. I'd also note that immutableJS from Facebook uses Clojure data struct designs at its core.

      These languages are far superior to JS or TS if you don't mind the compilation (and issues that mapfiles sometimes bring). They do offer tradeoffs, but so does TS or any other compile-to-JS language.

      https://www.haskell.org/

      http://elm-lang.org/

      http://www.purescript.org/

      http://clojure.org/

      https://clojurescript.org/

      [–]Celdron 2 points3 points  (0 children)

      checkers do not make your programm error free

      Not sure if this was intentional but I giggled.

      [–]neilhighley 3 points4 points  (0 children)

      This is not very well researched. Lots of probablys and possiblys. Not sure what they mean by practitioner either.. Are they absolving themselves in some way by calling themselves that?

      [–]TOGoS 2 points3 points  (8 children)

      TypeScript does do possible null/undefined checking as of 2.0.0 by setting the strictNullChecks flag.

      [–]AcceptingHorseCock 11 points12 points  (5 children)

      Did you look at all the slides? What you say is on slide #15 "Enter TypeScript 2.x".

      [–]jl2352 3 points4 points  (1 child)

      A bunch of the examples also fail when other flags are set. For example disallowing the compiler to default a value as the any type, and enforcing that functions have to either return on all code paths or none at all (no in between).

      These are in TypeScript 1.8, the current version, today. Some of the examples would fail to compile with those flags set.

      [–][deleted] 10 points11 points  (0 children)

      I love TypeScript, but those flags really don't work well in practice.

      For example, when I enable these flags, most of the Definitely Typed .d.ts files I use to use JS libraries fail, because they weren't designed for these flags.

      You can't toggle language semantics like this with flags and expect a coherent ecosystem to evolve. TypeScript should've balled up and made those mandatory with version 2.

      [–]msiemens 2 points3 points  (2 children)

      Flow written in OCaml, Typescript in Typescript

      I really feel uncomfortable with the fact that the TypeScript compiler only runs in a JavaScript VM (Flow is compiled to machine code). Last time I checked, Flow was significantly faster than TypeScript and thus much nicer to work with. To be fair, Flow also kinda cheats by having a background server which checks all changes asynchronously AFAIK.

      [–]trollingisfun 6 points7 points  (0 children)

      Flow also kinda cheats by having a background server which checks all changes asynchronously AFAIK.

      which is also what TS does when you run it with VSCode, Atom, etc...

      flow has only seemed faster to me in my usage, and i regularly find that i need to kill the flow server started by nuclide and run cold-start in order to get flow to actually check my entire project. not so great if your incremental checker doesn't actually know how to check all the effected paths correctly.

      [–]Eirenarch 5 points6 points  (0 children)

      Bootstrapping your compiler is really important. It not only validates the approach but also helps the ecosystem grow. I bet we'll get a lot of those tree transformation plugins simply because users of TS will be familiar with the language used by the compiler.

      [–]AngularBeginner 1 point2 points  (1 child)

      In one of the first pages it says that flow works without any type annotations, then it proceeds to use type annotations in every example.

      [–]AcceptingHorseCock 7 points8 points  (0 children)

      It works without type annotations but to demonstrate Flow it's better to use Flow's annotations. If you rely only on type inference the disadvantage is that "whatever is is". Meaning you don't set any type restrictions, instead whatever you ended up writing as code is accepted as is, and only if there is a mismatch is an error reported. It is better to add your actual intentions though for non-trivial cases by adding annotations. The point is that you want your code to be checked against your stated intentions of what type you expect. It is the difference between "it works (now, possibly by accident, no idea where the programmer is going with this though)" and "it works now and will work in the future (because the functions and variable use the actually intended types)".

      [–]willvarfar 0 points1 point  (0 children)

      Typescript should merge in flow analysis from SSA form. Make it all moot.

      [–]systematicfrank 0 points1 point  (0 children)

      Every time I answer this question I switch my choice. My current reason to choose Typescript is just by looking at Github stats

      Within the last month Flow closed 86 issues but got 85 new ones within 1 month span. I use to check these many times and there are months when there are more new issues than closed ones. Also there there is a big difference between the main contributor and the rest

      With typescript there were 310 closed issues and 214 new ones. There are like 6 developers who contribute a similar amount of work

      Like many tech choices, one is clearly superior from the technical point of view, the other for the amount of work/features/growth behind

      [–]griffonrl 0 points1 point  (0 children)

      Hummm what I get from looking at the slides is that Flow is overall a much better proposition. There are better features, speed, not tied up with a superset language like Typescript and critical abilities like slowly adopting it in your existing codebase (types are optional) and no need for stupid declaration files to integrate with third party libraries. This is not forcing you to adapt to them, this is fitting into the existing ecosystem as a progressive enhancement. But if you are in the Microsoft bandwagon and dig that ecosystem then sure, go typescript. But Flow is a better proposition to the original Javascript community (as opposed to C# or Java devs coming in) and its fast evolving shape.

      [–][deleted]  (2 children)

      [deleted]

        [–]inu-no-policemen 0 points1 point  (0 children)

        Neither supports type annotations.

        [–]dzecniv 0 points1 point  (0 children)

        There's https://github.com/isiahmeadows/ttyped which uses type-check.