Quite a bit of this comes from ES6 improvements which Typescript incorporates (and transforms to sensible ES3 output) - for example
real classes, and
Syntactic sugar aside, there are a few reasons I like Typescript. An improved IDE experience in VS (and VS2012 is already quite good with intellisense via jsdoc comments and JS execution). Static typing improves the self-documenting nature of code, helps enforce a cleaner design, and ensure program correctness. Type definition files are available (the DefinitelyTyped project maintains a good selection) for popular JS libraries to allow their use with full type information in a Typescript program (and this interoperability is huge).
There are 2 ways to approach features which cannot be typed in an existing version of the type system, one is to refrain from using them in order to improve your program’s maintainability, ease of understanding, correctness etc (the lint-style approach of using “the good parts”), the other is to enhance the type system to be more expressive.
any type covers all the cases where the type of an expression can be basically anything at runtime. This allows for the awkward
cases where the type system is not powerful enough to express what the programmer knows - an escape clause. It also functions as the type
When developing Typescript code with the intention of using full type annotations and achieving type safety, this implicit ‘any’ typing can be more of a nuisance than a help. In fact, since Typescript has type inference this becomes rather hard to spot - you don’t need type annotations everywhere, just wherever the type system is not able to infer the correct type. But you might assume that a type is inferred where in fact it is just implicitly ‘any’, and then you have the misapprehension of type safety without any of the guarantees.
Typescript 0.9.1 introduces the
--noImplicitAny flag to disallow such programs. Then the above program will not compile:
any.ts(23,12): error TS7006: Parameter 'n' of 'f' implicitly has an 'any' type. any.ts(23,15): error TS7006: Parameter 'm' of 'f' implicitly has an 'any' type.
Functional languages have had the notion of “polymorphism” for a long time - this is when data structures and functions can operate over any type. Often this is used with lists, for example this F# function works to repeat an element of any type into a list of repetitions of that item:
'a is a type variable, standing for any type (and
'a list is a list of things of that type). This is in the F# core
In contrast to this “parametric polymorphism”, object oriented languages have long provided a different feature of “subtype polymorphism”. This is classically useful to treat your button and textbox alike as widgets to compose your UI (and many other things). One obvious thing that this does not help with is the case of homogeneous collections, and so the mainstream OO languages (C++, Java, C#) now (eventually!) all have a form of “generics” which allow us to express strongly typed operations over arbitrary types (“generics” and “[parametric] polymorphism” are terminology for the same thing from different worlds). For example, the above in C#:
(this is a naive version of LINQ’s Enumerable.Repeat).
Note that without knowing the type of
x, we’ve assigned it the
any type, and as a result the function returns
(if we omit type annotations on
l they would be implicitly
any to the same result).
Typescript 0.9 introduces generics syntax which should be familiar as above, and we have:
And this function returns
This might all seem a bit academic, but I think it’s huge. As an example take the library
Underscore.js. This provides
a bunch of utility functions for working on lists and collections (familiar to the functional programmer/LINQ user,
and some of which are in some JS implementations but not present on all browsers).
Prior to 0.9, many types would incorporate
rest which returns the rest of a list after skipping the first
(or first n) element(s):
Now this can return the same type of array:
Knockout has the notion of observable properties - to create such a property we wrap it in a call to
The pre-generic typing of knockout had some fixed overloads for built in types
string, but if you use
a user-defined type, you were cast back into
any-land. Now with generics we can have an
Note, I did not specify the type of the observable. If I run
tsc -d on the above input I get the resulting types inferred:
The difference between these two typings is that the following mistake will be rejected by the generic typing:
The addition of generics to Typescript probably marks the point where if you’re thinking of trying it, it’s worth
doing so, particularly if your favourite JS libraries have typing definitions available
(again, check DefinitelyTyped). There are a number of other improvements
in these recent releases (0.9 /
0.9.1) - overloading on constants is also
quite funky. It’s also worth trying
--noImplicitAny, though you might well decide it’s not for you.