JavaScript is the language of the Web, but it's tough to manage for enterprise-scale development.
Historians who reflect on
JavaScript's emergence as a dominant programming language in the 21st century
may find themselves quoting Donald Rumsfeld: "You go to war with the army
you have, not the army you might wish to have."
For growing numbers of programmers,
JavaScript is the army we have. As we send it into the field to tackle ever
more ambitious engagements both client and server side, we find ourselves
battling the language itself.
JavaScript was never intended for
large programs built by teams that use sophisticated tools to manage complex
communication among internal modules and external libraries. Such teams have
long preferred strongly typed languages like Java and C#. But those languages'
virtual machines never found a home in the browser. It was inevitable
that JavaScript alternatives and enhancements would target the ubiquitous
JavaScript virtual machine.
Among these is TypeScript, the
brainchild of Anders Hejlsberg. I would not have predicted that the creator of
Turbo Pascal and C# would, in 2015, be working in the open on GitHub, for
Microsoft, to strengthen the Web's native programming language. But it's a
delightful outcome. TypeScript is an important project that delivers useful
benefits now and is moving forward nicely.
The TypeScript language is most
succinctly described as an optionally typed superset of JavaScript. Since
existing JavaScript is valid TypeScript, you can begin using the TypeScript
compiler -- and TypeScript-aware tools -- by simply changing filename
extensions from .js to .ts.
That turns out to be a good way to
start. TypeScript can be immediately useful, even before you add any type
annotations to your own code, thanks to the type definitions collected at
definitelytyped.org. The definitions available there, for hundreds of
JavaScript libraries (including jQuery, Angular, and Bootstrap), describe the
interfaces exported by those libraries. TypeScript-aware tools use those
definitions to flow type awareness into TypeScript programs that import the
annotated libraries.
That same kind of type awareness is
also available, in a portable way, for JavaScript's core library and for the
browsers document object model (DOM). It's portable because TypeScript is
written in TypeScript, targets JavaScript VMs on any platform, and provides not
only a compiler but also a set of language services that support code
intelligence. Visual Studio is one consumer of those services. Others include
WebStorm, Eclipse, and Sublime Text. There's also the TypeScript playground, an interactive Web page
that completes statements, prompts for parameters and their types, and warns
about type errors.
Second
time's the charm
When I took my first run at
TypeScript in 2013, I wanted to stick with the language but didn't for a few
reasons. The compiler was a bit slow back then, and a delay of even a few
seconds frustrates a JavaScript developer accustomed to instant results. Type
definitions were scarcer and less mature. Plus, some basic JavaScript idioms
required workarounds.
When I tried again in late 2014 I
found none of those problems. But my experience was also better, I think,
because I approached tasks in a more incremental way.
The first time around, I immediately
began refactoring my code to take advantage of TypeScript's support for
classes. That's one of the features of the forthcoming ECMAScript 6 that
TypeScript makes available now. You can express object-oriented idioms in
tomorrow's JavaScript syntax and use the compiler to produce the less
convenient and less readable idioms that work in the browser today. In
retrospect, the top-down approach wasn't the best way to get started.
The second time around I took a
bottom-up approach. I started adding type annotations to otherwise unaltered
JavaScript code. As I did so, my grasp of the code improved. Even though mine
wasn't a large program, JavaScript's implicit conversion among strings,
numbers, and dates had made it hard to visualize the types of objects that
flowed into and out of functions. Of course, you can document those
expectations in comments, but without strong tool support, such documentation
drifts away from the reality of the code.
With TypeScript that documentation
lives as part of the code during the development process, and enables an IDE --
in my case Visual Studio -- to bring the documentation to life. But it's all a
convenient illusion. When you compile to JavaScript, the annotations fall away.
If you've done no more than add such annotations, the resulting JavaScript will
exactly match your original unannotated code. (If you have restructured the
code to use classes and modules, you can use the JavaScript source map the
compiler emits for TypeScript-source-level debugging in browsers and
stand-alone debuggers.)
"Instead of having a switch
that turns types on and off," says Anders Hejlsberg, "we have a
dial." You can invest incremental effort for incremental reward. As you
add annotations, you improve your own ability to reason about the code, and you
enable tools to provide more powerful automated support for that reasoning.
There's also a multiplier effect
because the TypeScript compiler works hard to infer types where it can. If you
tell it that a function returns a string, it will know that a variable holding
the result of that function is a string, even if you haven't annotated the
variable with the string type. If you later try to assign it a number, the
compiler will complain.
Once I'd checked all my primitive
types I began writing simple classes to model JavaScript objects made from
primitive types. As I added type annotations for these compound objects, Visual
Studio made their members available for code completion. Functions that
received -- or returned -- those objects as parameters became self-describing
and self-checking. Again this code awareness flowed through the program. In
JavaScript you can't know, a priori, whether the return value you're assigning
to a variable is of the type you expect. That uncertainty results in much
confusion and error. Why tolerate it?
There's
a test for that
The growing popularity of
dynamically typed languages like JavaScript happened to coincide with a growing
appreciation for the practice of writing self-testing software. As a result,
there's been some tendency to conflate the two trends. If your test coverage is
sufficiently robust, some say, there's no reason to incur the overhead of
static types.
We can debate the feasibility of
writing tests that obviate the need for static typing. But if you buy the
argument that type safety becomes important at large scale, TypeScript invites
you to consider how you want to invest your testing effort.
Tests are, after all, another kind
of overhead: more code to write and maintain. Arguably what can be tested
mechanically should be. If computers can figure out whether two software objects
are compatible, humans ought to delegate that job to them. Writing tests, like
writing the software those tests exercise, is a creative act that should
require and benefit from human intelligence. Automatic type checking is, from
this point of view, a way to free up human creativity for higher
purposes.
One of those higher purposes is
effective naming. "There are only two hard things in computer
science," it's famously said, "cache invalidation and naming
things." The names of variables, functions, classes, and modules are the
most fundamental kind of documentation.
It's hard enough to coin names that
usefully describe their roles in a program. It's even harder to adjust those
names as those roles evolve during the ongoing development of a program. That's
partly because naming anything well -- in software or in any other domain -- is
intrinsically hard. But in software there are special risks when names that
appear in different contexts, and mean different things, can't easily be
recognized as such. That's the situation in JavaScript. There are a number of
incompatible workarounds for organizing code into modules, but the language
itself doesn't support any of them.
ECMAScript 6 takes a major step
forward. It provides a standard way to organize programs, which may spread
across many files, as sets of modules. That mechanism, which TypeScript adopts,
is a boon for large-scale development. When module dependencies are declared in
a standard way, programmers can more readily understand those dependencies, tools
can automate that understanding, and code refactoring becomes less risky.
For example, in a conventional
JavaScript environment it's risky to rename a module-scoped or class-scoped
variable, function, or class that's referenced in many places, perhaps from
many files, because there's no way to know if the name is intended to mean
something else in another context. A TypeScript-aware IDE knows and can make
such refactoring a safe operation.
Culture
shock
Despite its advantages, TypeScript
faces an uphill climb for reasons that are more cultural than technical.
Developers prize JavaScript's freedom of expression, and while TypeScript works
hard to be unobtrusive, its mission requires developers to voluntarily give up
some of that freedom.
The benefits become clear at large
scale, but many JavaScript projects aren't operating at that scale. One that
is, Mozilla's Shumway, implements a Flash-compatible runtime in more than
170,000 lines of TypeScript. It's easy to appreciate why a project of that size
would need industrial-strength type checking. For many projects, though, the
need doesn't seem so compelling.
Then there's the Microsoft factor.
Its rocky relationship with open Web technologies over the years has left many
Web developers with a sour taste that won't easily dissipate.
TypeScript is, objectively, doing
everything right. The project is being developed in the open on GitHub, under
an Apache 2.0 license, and it accepts community contributions. The vast majority
of pull requests are from the GitHub accounts of Microsoft employees on the
core team, naturally, but you can also find community-contributed bug fixes.
This is not the behavior people have learned to expect from Microsoft, and it
will take more than a project like TypeScript to change those expectations.
What has turned some heads is
TypeScript's relationship with a couple of other projects with similar goals:
Google's AtScript (which is being used to build Angular 2.0) and Facebook's
Flow. AtScript is exploring the idea of runtime as well as static type
checking, while Flow hopes that aggressive type inference can minimize the need
to annotate existing code bases and simplify the use of type checking for new
development. Both evaluated TypeScript, and neither adopted it. But everyone
agrees that type checking for large-scale JavaScript development is an idea
whose time has come.
More accurate, it's an idea whose
time has come back around again. TypeScript's type annotation syntax originated
in ECMAScript 4 and was implemented in ActionScript 3, but never landed in the
ECMAScript 5 that runs in today's browsers. Type annotations aren't part of the
forthcoming ECMAScript 6, but are widely expected to land in the next
incarnation of the language. Nobody knows what those annotations will be. But
AtScript and Flow are betting that they'll look a lot like the TypeScript
syntax, so they're aligning with it.
When JavaScript expert Axel
Rauschmayer wrote about TypeScript, AtScript, and Flow on his blog, the first comment
was: "Hmm, when Facebook, Google, and Microsoft are working together it
kinda looks like future of the Web." It does indeed. That future has been
a long time in the making, and will unfold gradually, but the reinforcements we
need are on the way.
Read More News :- Techies | Update
No comments:
Post a Comment