To me, this appears to be the way to go. Javascript + Typescript. Rather than deciding on weak (dynamic) typing vs strong typing, you pick both - incremental typing, as allowed by Typescript.
Want to bang up a quick solution, as in MVP?
Use bare-bones Javascript, it is all valid Typescript. So you get dynamic typing. And if you do not care about strong typing, you can just stop right there.
But if you, some day, for whatever reason, decide that you feel like strong typing: good - you do not need to rewrite your app in a different language - just go back to your code and add some type info, here and there, at your leisure. As you do that, you get all the benefits of static typing, ie compiler showing you obvious type-related errors, correct keyword-completion, exact refactorings, etc etc.
> Want to bang up a quick solution, as in MVP? Use bare-bones Javascript
Actually, adding the bare minimum of type annotations (fields & function signatures) and type casts (e.g. casting whatever you get from querySelector into the concrete type of element) results in fewer key presses, because you can auto-complete everything and because you get additional machine-assistance like call tips and type checks.
So, you'll be actually faster if you add some types. Type inference does cover quite a lot. In practice, you'll need very few annotations and casts.
This Dart demo, for example, only needed a single type cast to be fully typed:
The thing I found is that the safety benefits of static typing are pretty all-or-nothing. If your whole program is typed, you can maintain a much smaller level of test coverage and have the same defect rate (or alternatively you can maintain a much lower defect rate with the same level of test coverage). But untyped parts are "infectious": a type error in one part of a program can show up a long way away, having silently propagated through your generic code until it hit something that made very concrete use of the value. So if even 10% of the code is untyped, you end up needing the same test coverage you would in a dynamic language.
When I bang something up, I'll use Visual Studio 2015 and Typescript from the get-go, now that I'm used to it I find it much faster due to the Intellisense on all my code, and all the browser code too (and anything else I add typings for [1]).
I find it way, way, way more productive than plain old JS development without an IDE.
EDIT: I always turn off optional any types, so everything has to be type annotated, even if that means I simply cast to an explicit <any>. I find that non trivial problems in JS become so much easier in TS due to the compiler and built-in refactoring tools. I can't think of anything negative to say about TS at all!!!
We've been using it over at Ionic, and that's exactly what we've found as well. Types are great...but they're overhead that most apps don't need on day one. When you just want to get something up and running you can skip them. Once you dig in and really build out the application, you can add them and get a bunch of great benefits (type safety, autocompletion, "free" API documentation, etc.).
On top of that, tsc is possibly the fastest/easiest to use transpiler out there, which helps.
You consider typing to be an over head? Do you really reuse variables within a scope to refer to different types? I feel like that would produce confusing to read and use code.
IMO dynamic typing is hard to work with and slows things down. "Auto-typing" or type inference like in Swift, Kotlin, or Dart is the most amazing thing ever. It gives you the safety of static types and the "speed" of coding of dynamic types.
I think the overhead here is the programmer time spent specifying the types in a program, which is why everyone loves type inference.
This is a common communication error: when you read "typing" you think "static type system", but when the parent wrote "typing" it almost certainly meant "explicit type annotations".
"I think the overhead here is the programmer time spent specifying the types in a program"
There are different overheads on program structure and verbosity which goes way beyond type annotations, depending on the language used and the style of the particular developer.
For example, in dynamic languages, a single container such as a list can contain any entities and functions can accept any entity as a parameter.
Java and C# can achieve this same using just object handles - but in other statically typed languges one either implements several containers and functions, or uses or creates an algebraic datatype using the language native typing (i.e. Scala, F#, etc) or invents ones own which is then utilizes in the container signature or function definition.
No I understand, which is why I think type inference is a much better solution than dynamic typing. I use Python and JS often and I am constantly looking up types of arguments for functions and what their return types is. JSDoc helps, but its pretty tedious. I think dynamic typing is much slower to actually code in.
Personally, I agree with you that, once you know the type system, you're more productive with it. However, TypeScript is new, and can be difficult to transition to for some people. One example is dealing with some gotcha's like adding new properties to things like window: http://stackoverflow.com/questions/12709074/how-do-you-expli...
Is the type system that different from Javascript? I remember looking at it back around 1.0 days and it seemed like basically the same as Javascript, which was one of the reasons I decided not to pursue implementing it in my work.
How is this different from using Facebook Flow? I have been using Flow on a JavaScript project, along with Babel for ES6, and enjoying the experience quite a lot.
Typescript is older (2012 vs 2014), more mature and stable (v1.7 vs v0.x), has better tooling support (autocompletion in Visual Studio), is easier to install (you only need NPM), has better documentation, and is easier to Google (try searching for "flow" online!). There are also plenty of common libraries with Typescript annotations, so you can just use e.g. Phaser and Typescript together without any extra work. Other than that Flow and Typescript are fairly similar. Perhaps someone who has used Flow can explain what makes it different from Typescript.
Flow offers some interesting control over things like optional types (nullable) and intelligent understanding of type tests in conditionals or calls to libraries like invariant. I've had these sorts of features catch quite a few bugs in my editor before even running a single test.
Flow is also based on a daemon which continuously monitors your code. As such, it incrementally checks your modules allowing it to be extremely fast once started.
I ended up using flow since it fit with the language feature set I was using with Babel (JSX in react code being one example). Since then, I've grown to enjoy the flow based typing and the rather good support for optional and non-optional types.
Looking at the code lately seems to show some interesting stuff in the pipeline too. Taint tracking seems like a very useful one that I'd love to implement and seems like a natural extension of the code-flow based type system.
Flow could definitely use more documentation and more example code but I found the community on IRC extremely helpful and polite so perhaps it's not a bad time to start if you're willing to do a little reading on the site first: http://flowtype.org/docs/getting-started.html
TypeScript has type guards, which covers #1. Also has custom type guards, which lets you write your own checks that constrain union types.
TypeScript also has a language services server which runs as a daemon, lets you submit incremental edits to it and supports services such as autocomplete, rename refactoring and pretty much anything you see in visual studio or visual studio code.
But yes, the type system has a couple of unfortunate flaws that are relics from its beginnings (cant express non-nullable types).
This is a neat idea. Even with a significant perf hit, it could be used during development, testing, and debugging. You should propose this to the Typescript team! https://github.com/Microsoft/TypeScript/issues
No, and you wouldn't want the overhead. You can turn on warnings though if you want to make sure all your code is typed on compile. After compiling all type definitions are stripped and you're left with plain javascript.
swax is probably referring to the compiler option "noImplicitAny", which can literally turn variables whose type is not explicitly specified and cannot be inferred from their declaration as errors, instead of assuming they have the transparent `any` type.
>To me, this appears to be the way to go. Javascript + Typescript.
This is exactly how I feel. Typescript is amazing, It feels simple and powerful at the same time. It appears too good to be true, and I will never write plain java script again.
Want to bang up a quick solution, as in MVP? Use bare-bones Javascript, it is all valid Typescript. So you get dynamic typing. And if you do not care about strong typing, you can just stop right there.
But if you, some day, for whatever reason, decide that you feel like strong typing: good - you do not need to rewrite your app in a different language - just go back to your code and add some type info, here and there, at your leisure. As you do that, you get all the benefits of static typing, ie compiler showing you obvious type-related errors, correct keyword-completion, exact refactorings, etc etc.
Looks like the best of both worlds.