Glimmer.js: What’s the Deal with TypeScript?
medium.com
medium.com
Once a JavaScript project scales beyond what can fit in your head, JS's initial productivity boost crumbles because you have to constantly double back and make sure your methods/constructors/etc. are correctly used, which properties are optional, etc... A lot of the debugging happens in runtime and god help you if you try to make a breaking change to one of the major classes/apis in your project.
It's not unbearable, but the main reason for using JS is because of the productivity it allows.
With TS for the cost of taking the time to explicitly define your data you get a C#/Java level of debugging that has clear productivity gains and shifts your debugging from the browser/console to the IDE.
And when something doesn't fit the TS model you can just exclude it or only type the wrappers that integrate with the rest of your project.
That and async/await is a godsend over promises.
For kicks I tried the online Elm demo. Offhand it doesn't seem like Elm highlights errors inline(?). The syntax also looks a little foreign, whereas TS generally still looks like JS with a few exceptions.
I imagine Elm/Flow both have this, but another thing I like that TS does in VSCode at least with a watching task is collecting errors project-wide in a "problems" window.
Please try Elm and email me with your feedback. Id love to know more about it. Im a programming languages nerd. :)
- You need to like Elm the language (it's pretty good, but limited, not expressive)
- You need to like purity. Time.now or Math.random returns an asynchronous Task. I know why it's done like that, I just don't agree with the tradeoff.
- You need to like Elm the ecosystem or be prepared to write lots of awkward JS glue code
- You need to like Elm, the architecture (it's simple, but has tons of boilerplate and limitations)
- You need to accept Elm, the roadmap made by a benevolent dictator. The progress is slow.
Compared to a good typescript codebase, you will get like +5/10% type safety. Typescript is way more flexible, but that also mean you will have to rely a bit more on human code reviews, etc rather than the Elm compiler just telling you "no, there is only one way to do this". On the other hand, you have just typescript on one side, Elm + javascript/typescript if you want to achieve anything serious on the other :)
Go with Elm if you like being in a very, very controlled environment (frameworky) and you're afraid to make mistakes. Go with typescript if you're a hacker who like to mix and match architectures, libs, etc and accepts things change fast in the frontend orld right now.
In my experience whenever I worked on a JS project on my own, there was an upper limit to how far I could keep writing the code on my own. After that, I had to spend time in doing other things (like writing Integration tests, lots and lots of unit tests, or refactor existing code because I realized that there are many issues unveiled).
But now, with Elm, it's like a whole set of unit tests are being written at the time of writing code which take care of plenty of common errors usually made due to lack of a good type system.
Add to that the usage of Maybe types (which are very beneficial in avoiding some UI antipatterns[1]), and the Reactive Programming pattern, I feel like I am writing a lot less code than what I am used to writing in JS projects.
I highly recommend Elm to anyone who wants to write a personal project, you'd see what benefits I'm talking about.
1. http://blog.jenkster.com/2016/06/how-elm-slays-a-ui-antipatt...
The first is that it made some specific workflows a lot easier. In particular, I'm working on some pre-alpha libraries where there's movement on how the API interface is defined. TypeScript made that transition a lot easier. Yes, my testing would have eventually caught all the method arity mismatches, but TypeScript made this happen about an order of magnitude faster.
The second is how unobtrusive the types actually are. I did a fair bit of J2EE programming in the 00s, and types and interfaces can be really annoying. With typescript, interfaces are assertions about the shape of an object, rather than things themselves. That means, if you defined an interface as HasFirstName: { firstName: string } and function greet(person: HasFirstName), you don't actually have to put HasFirstName everywhere in the code that uses that function. You're not required to set up inheritance or anything. You just have to make sure that all arguments to greet have a firstName property. That's it. So I can say: const dude = { firstName: 'the' }; greet(dude) just fine. But if I try to greet(potato), it'll error.
Lexical typing this way gives you a lot of power while still staying out of your way in a language like javascript where it's super common to create consts as bags of properties without worrying about what particular interface they're instantiating. I really like that, as it is precisely the overbearing types of Java that annoy me.
I think the upsides are quite well known by now. Honesty requires me to admit that I did run into some downsides:
- Initially it was difficult to understand the exact mechanics of how typescript ... types. Definition files seemed like a bit of a black art, and how to annotate existing code so that it had the proper type wasn't always obvious, especially when you run into libraries with incomplete or wrong type definitions and when you want to do tricky stuff like creating typed mocks in unit tests. The typescript documentation is very good and I haven't needed much beyond it, but some extra real-world type definition chapters would help.
- Setting up a complete dev toolchain is challenging. I wanted everything: source maps, in-IDE debugging with breakpoints, in-IDE unit tests with code coverage, tslint, gradual introduction into an existing codebase, and robust integration into the build of the rest of the app (which in my case meant SBT integration). I still don't have code coverage in my in-IDE unit tests. The way I see it though, if your javascript has any build step at all you already have this pain, so this isn't so much a problem with typescript as a problem with javascript build pipelines in general.
- Convincing other developers typescript has value and isn't javascript's weird ugly nephew is an uphill struggle. Once you do a typescript project you end up understanding the value, even if you might not find it valuable for yourself personally, so it's only a matter of convincing developers to give it a go. However, getting to that point is a bit of a chicken and egg problem.
I feel the same way about Elm, F# and Fable, Facebook's ReasonML, and any other language that has an ML type system and compiles to javascript. I think the value becomes more apparent when: a) you work in a large codebase and have to refactor either a large swath of code and/or a critical piece of logic and b) you need to make illegal states unrepresentable. In both cases, I have found having a compiled, ml-typed language extremely helpful.
I think for both Typescript or an ML language, having immutable non-nullable types by default really cuts down on complexity - instead of having to specify everything that's immutable with something like a `const` keyword, you instead have to specifically point out which attritibutes on a type are mutable. That's a small win but has huge benefits - especially when you're trying to debug code.
That's just my two cents anyway.
import flatten = require('lodash/flatten')
TS expects any modules imported using ES2015 import to have the shape of a ES2015 module. This is an issue for many UMD/commonjs modules. In the case of lodash, it's effectively doing this: module.exports = flatten
And then you're importing it like so: import flatten from 'lodash/flatten'
and that is being transpiled to something like: var flatten = require('lodash/flatten').default
Note the default.I haven't migrated to webpack 2, but some brief experiments suggest all modules get massaged in to ES2015 format.
So far (a bit unexpectedly) I didn't really run into any nasty side-effects or things that went wrong with it.
See https://github.com/Microsoft/TypeScript/wiki/What%27s-new-in... for a (short) explanation.
Part of me wants to wait out the Flow team come up with better IntelliSense support. The `flow ide` command in the release 0.42 is a big step in the right direction. But it seems like TypeScript already has this, and if the delta between the two type systems is small, I might just go ahead and switch.
I suspect switching from Flow to TypeScript would be relatively straightforward as far as the types go, but going the other direction would not.
This presentation [1] was posted to HN recently and gave a pretty good overview of the differences between TypeScript and Flow.
[1] https://djcordhose.github.io/flow-vs-typescript/flow-typescr...
You can already see the conflict happening as some people prefer Flow and others TypeScript. Perhaps later Google will throw their hat into the ring and introduce GScript. Then, you have three different languages that introduce similar functionality, that all transpile into JavaScript.
Sound familiar?
Also, TS is a superset of JS, so the fact that it's a different language isn't really problematic.
There is a huge push going on. But Javascript has a consensus driven community: all the big players involved have to agree on something for it to be adopted (Google, Apple, Microsoft, Mozilla, etc.). Plus, even when it's adopted there's usually a 2-5 year delay before mass diffusion.
Google had one called Atscript, but rallied Angular 2 around Typescript instead.
http://sdtimes.com/google-microsoft-combine-typescript-atscr...
All the others were apparently decided by fiat in earlier days then grandfathered in. TypeScript is the first, and so far only, language to successfully go through the official approval process.
I feel like we're going to see a big increase in TypeScript related activity from Google in the next couple of years, due to this.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Type...
console.log("hello");
typedArr[0] = incompatibleType();
In javascript, it will produce "hello" as output, and then a run-time failure.https://developers.google.com/closure/compiler/
Code checking. The Closure Compiler provides warnings for illegal JavaScript and warnings for potentially dangerous operations, helping you to produce JavaScript that is less buggy and easier to maintain.
[1] https://github.com/facebook/flow/issues/245 [2] https://github.com/facebook/flow/issues/869 [3] https://github.com/facebook/flow/issues/1528
I'm curious why you think "why not just fb flow" for somebody who wants typed JS. It's certainly an option, but it hardly seems the go-to solution.
I really enjoy Swift, so I'm not put off by types. But I find the experience of working in a real typed language to be very different to working with Flow or Typescript, where the types are for pretend, and type definitions are wrong often enough to be a real pain. And I found my self evaluating npm packages based on their type definitions, and not their suitability for the task, which seems bonkers to me.
Also, I don't ever recall staying late to track down a bug that types would have fixed. But I've wasted many an hour tracking down bugs caused by mutations, and the state of Immutability and Typed Javascript is pretty grim as far as I can tell, unless I'm missing something.
Well, I still love TS though.
You definitely are missing something. Immutablejs and TS go together fine. Assigning to an immutable property or object is a syntax error instead of a runtime error. It's great.
And when webassembly arrives that will be over, and Typescript will be deprecated. I can't wait for a better modern language like Haskell, Python, Livescript, etc.. built on top of webassembly. Then we can finally stop trying to fix Javascript's flaws with new language features.
Manipulating the DOM from wasm shouldn't be any slower than Javascript. Slow in general because of the DOM, perhaps, but not because of wasm.
> And when webassembly arrives that will be over,
I really don't think this is true. I certainly agree that JavaScript isn't the perfect language, but it's a _very_ popular language. Even on the server-side, where right now you already do have the freedom to use languages like Haskell, Python, etc, you see a majority of developers now opting for Node.js. Even for desktop apps and data scientists, it's the most popular contender (all according to the latest SO survey).
You can argue about reasons all you like, but I don't think the people using JavaScript on the web are doing so only because webassembly isn't easily available yet. I think they're doing so because, for better or worse, they genuinely want to be using JavaScript (or very closely related languages like TypeScript).
"'compile the VM' strategies increase the size of
distributed code, lose browser devtools integration, can
have cross-language cycle-collection problems and miss
optimizations that require integration with the browser" [1].
My prev comment was speculative, but my point is that its not going to be a piece of cake to just drop another high-level language on-top of WASM and use it as a 'better' scripting language without having to pay some overhead costs, one being GC issues.[1] https://github.com/WebAssembly/design/blob/master/FAQ.md#is-...
Of course, lots of other problems remain, for example, downloading an entire runtime or "putting Python on WASM isn't going to magically make it fast". But I don't think the GC should be a particularly large challenge.
is basically a better way to do ASM.js . How many Python,Haskell,Livescript have been built on top of ASM.js ?
Do you really believe you can make your users download 10s of megabytes of binaries each time they visit a website just to bootstrap a language? And i'm not even talking about the runtime...
Right now, the only viable languages for webassembly are the ones that don't use garbage collection and have a limited runtime, Rust,C and C++ .
If people start writing Python for the web for no other reason than they just dislike JavaScript we're going to be forcing users to download a dozen different runtimes, just because of developer preference. This isn't a good thing.
I remember seeing a demo of React Canvas a few years ago - basically, recreating a "DOM" of sorts inside a canvas tag - and the performance was crazy. Beautiful 60fps touch interactions. But, of course, it only does a tiny subset of what the DOM does. I'm still waiting for a good reason to use it myself to try out how the API feels.
Why would users need to download a runtime, given that we'd have WASM as a compilation target for Python, the language?
I mean, on the backend, there's no ultimate technical reason why you couldn't switch -- the closest you can come to the browser situation is the limited PHP hoster of the early oughts -- and still we don't see a rapid progress away from awful languages. Just more people duct taping said languages into something slightly more sane.
We'll get the same for JS. It's the new Pascal/C in that regard.
Much of that is already possible and guess what, neither TypeScript nor JavaScript are deprecated.
WebAssembly is very cool techonology, but it's not going to deprecate Javascript because Javascript will be, at least for a very long time, the only scripting language that runs efficiently on the web, and also will always be the most well supported.
With WebAssembly you could write in any AoT compilation language that can compile on LLVM, but I, and many many other developers, have no interest in very low level languages like C, C++, or Rust in the browser, even though we acknowledge the flaws in JS. Maybe one day higher level languages besides Javascript will be practical, but that's a ways away.
I mean, that's kind of already the case when you want to ship a Python project as a stand-alone package to run on the desktop. Alternatively, I could see a method of installing runtimes into your browser like plugins so it doesn't have to be shipped over the wire every time. Not saying I'd ever want to do something like that, just that alternatives exist. Browsers are moving more and more towards VMs that transcend the context of a single synchronous request/response.
ES5 was a dumpster-fire. But ES2015+ is an amazing language. You just have to take the time to systematically study it.
If you're choosing a language you'll spend thousands of hours with, you shouldn't use "initial learning curve" as sole criteria.
make an object:
in ESx:
var myObject= {
a: {
b: {
c: {
d: 'some value'
}
}
}
};
in Coffeescript or Livescript: myObject= a: b: c: d: 'some value'
now use it:in ESx:
console.log myObject.b.c.d // crash, myObject.b does not exist
how to prevent? if ( myObject.hasOwnProperty('b') and myObject.b.hasOwnProperty('c') ){
console.log myObject.b.c.d // undefined
}
in Coffeescript or Livescript: console.log myObject.b?.c?.d // undefined
I can write almost a book with too many of such examples. So, NO it's not an amazing language, I wrote for many years in it and it sucks all the way.myObject= a: b: c: d: 'some value'
Is really _that_ much of an improvement over:
myObject = {a: { b: { c: { d: 'some value' } } } }
especially combined with an editor that will match those closing brackets for you. And the reality is that if you have object literals that deep, chances are the inner values will also be large enough to justify expanding it anyway.
Also lodash plugs a large number of holes in the standard functionality. In most projects I work at, I'd write something like:
_.get(myObject, 'b.c.d')
for your second example.
WebAssembly will be great, but as a complement to Typescript, not as a replacement. I would love to import a native module for the small chunk of my code that needs to do heavy lifting. And I don't see any reason why the Typescript team couldn't eventually build a WebAssembly compatibility layer.
E: i didnt mean this as a criticism
* find definition
* find usages
* auto import (never type "../../../../../dumb.js" manually again)
* er... types
Why?
It's certainly not a requirement of TS, any more than it is in JS, and I've seen people writing large TS codebases without classes. Typically with a much more functional approach though. I don't see people writing many prototypical objects with TS. Is there a good reason they should be?
Also, TS does not force you into OOP. TS codebase itself does not have any classes.