Javascript with static typing

Statically typed Javascript : Why and How

In the last months I have found good experiences using Statically typed Javascript. For example, using React with Typescript. It helps a lot to build a robust Web development, with statically typed Javascript support, ready for a complex and enterprise-level projects.

TypeScript is maintained by Microsoft, but it’s not the only option for statically typed Javascript. Flow, from Facebook and Dart from Google are similar options among a long list of implementations.

Why so many “big companies” are doing really big efforts to introduce static typing in Javascript development in the last years?

Why static typing ?

Static typing have some good benefits over dynamic typing in a professional environment:

  • Catching bugs earlier in the development cycle
  • Better testing plans, more robust and specific
  • Eliminate some classes of bugs in already deployed systems
  • Improved code-assist (auto-complete, suggestions, documentation), linting (code quality and standards) and other tools for IDEs/Editors
  • Enable compiler optimizations, refactoring and better minifying.
  • Cleaner looking and self-explaining code.
  • Better maintainability in the long term.

For people working many years with dynamically typed Javascript, it might sound very complex and difficult to do a “switch”. Taking advantage of the dynamic types and flexible syntax is a good help to improve the development efforts, but thinking about real-world and complex applications, in the long run, you can be surprised with a lot of errors, difficult to catch without type checking. Consider the following code:

function addNumbers(x, y)< return x + y; >

It looks simple, but it could have unexpected results with untyped parameters ( 3 is dynamically converted to string «3» before adding, changing to a concatenation):

Читайте также:  Php логирование sql запросов

Now consider the following example using static typing. There is no chance for unexpected results.

function addNumbers(x:number, y:number)< return x + y; >

The migration problem

Migrating a big Javascript codebase to TypeScript could be a big pain. But starting new projects with a structured and statically typed Javascript code could save a lot of efforts and time in the long term.

Even if you are planing to adopt static typing in current projects, this migration could be done gradually. Testing plan could be more strict for Typescript code, but current Javascript code could be tested as usual. Mixing different Javascript flavours is not a problem.

Typescript has a defined procedure to migrate Javascript code a.

Concrete benefits in numbers

As stated in the study To Type or Not to Type: Quantifying Detectable Bugs in JavaScript, there could be increasing benefits in adopting static types for projects. A mean of 15% of extra bugs detectable in systems that already have completed successful tests, only adding static typing checks and annotations.

Over 400 test-cases, Flow successfully detects 59 of them and TypeScript 58. Running a binomial test, at the confidence level of 95%, percentage of detectable bugs for Flow and TypeScript falls between 11.5% and 18.5% with a mean of 15%.

typescript flow detected bugs

Achieving these results doing static typing checks and annotations, gives light about the process of static-izing current Javascript code. It could involve extra work, but the effort is worth of it.

There is a BitBucket repository of test cases here. Also, the annotation tool they used to facilitate the process.

Knocking down the myths

Some people could be thinking about concerns and reasons to avoid using static types, adopting TypeScript or another typed language. There are some common misunderstandings about typed Javascript languages:

  1. Too strict: Loos of dynamism is often related to loose of productivity, but in the long term, and in growing codebases, this strictness is desirable and sometimes mandatory for enterprise-level development.
  2. Standards: While TypeScript is not an official Standard (nor Flow), it’s becoming an industry standard. Javascript has defined some basic types, and his standards are product of many years of “industry standards” becoming official in the latest specifications.
  3. Difficult to learn: Basically, these languages are supersets of Javascript, adding only type declarations and some language constructs. It could be natural to adopt these extra concepts without effort.
  4. Difficult to migrateand integrate with existing code. You can perform migrations gradually. Most of the common conversions to apply are very straightforward. Also, there are projects helping to do this migration easier, like TypeWiz, and doing automatic type assignments for the most known Javascript packages and modules, like DefinitelyTyped .
  5. Lack of Support. Actually TypeScript is a open source project with Apache 2.0 License, actively maintained and with a growing community. Language support in the most known IDEs is widely available (Eclipse, VSCode, Sublime, Atom)

Conclusion

Finally, is up to you to adopt a statically typed Javascript language for your development. If you consider the benefits in the long term, you could be saving lots of development and testing efforts.

By the other hand, in dynamic developments like prototyping and small projects, it could be better to keep working in the common way. But, the benefits of starting a new project with static typing from the beginning, could improve the entire development process. Sometimes, once people adopt this approach, going back it’s no longer an option.

Источник

Static Typing in JavaScript & Best Tools to Do It

Let’s multiply Object by a String and add an Array!

Said no sane developer ever.

Why not leave things as they are?

Once upon a time there was an App . It was made of common App building blocks. One of its important foundation stones was a UtilityBeltService (let’s call it Utils ). The Utils had so many methods that it was hard even for old master App builders to grab a proper one without a few minutes of reading its code. Many small type inconsistencies lurked in huge codebase. Disaster was only a matter of time…

One of the builders spent some time commenting all those methods with some odd annotations. But it only made Utils look ugly and did not help too much. The App said, it wanted to be clean and beautiful, to be developed agilely and smoothly.

The builders decided to send one of them to the dark wastelands of world wide web in search for The Solution. The chosen one spent several working hours in search of salvation and he brought back three magic books. They had to decide. And they decided. App was to be happy again and not only Utils would change…

The Solution: Type

What the builders thought they needed was static typing system for JavaScript.

To help them find bugs faster.

To make their code better.

Wait, but JS has types!

Yes. It has. But JS is dynamically typed. And it’s dynamically typed with great elasticity — that’s really useful in fast prototyping and simple one-job scripts. But when application grows this elasticity becomes real pain in the ass as type bugs come out in runtime or even after several months on production. And no, unit and e2e tests are not enough.

JavaScript uses coercion mechanism to deal with operations on vars of wrong types. For example «a» + 1 (which is adding String to Number) will go smoothly and return «a1» (as a String). Here Number 1 is implicitly converted to a String to fit the operation. And that’s how coertion works. It smoothly hides many little and nasty bugs!

Static Typing

Consider «a» + 1 expression. What if some kind of checker would test it before running application? It would say Hey! I can Add Strings or Add Numbers but I do not know how add a String to a Number? Aaargh…. And sane developer can decide now what he really needs. Maybe he wants to getCharCode(«a») + 1 or «a» + String(1) ? The first one returns number 98 , the second one string «a1» .

I’m sure that you remember all those JS tweaks related to coertion (and not only this). But I’m also sure that everyone makes mistakes. And few such mistakes in a huge codebase can make one spend several hours in chase of The Bug.

I have good news. Static typing can find it for you even without running an application 🙂

Statically Typed JavaScript

Of course it can be only some kind of fake static typing applied on top of JS in one or other way. Not a real thing.

There are three popular possibilities — jsDoc (with e.g. Google Closure Compiler), Facebook Flow and Microsoft TypeScript. First one uses comment like annotations — does not corrupt pure JS — while next two extend JS so they have to be transpiled. I will compare them briefly in a moment.

Before I start: this article does not touch AtScript as it left the scene in favour of TypeScript. Also I do not want to talk here about completely different languages compiled to JS like Elm, Dart, ScalaJS or anything similar. It’s just about static type system for JavaScript (and maybe little more).

JsDoc

JsDoc is annotation-like comment system that brings some standarisation to describing code in comments (based on JavaDoc). It’s easy to start, as you do not have to change your builds, tests, etc. — you can just add few comments here, few there and you have an inline documentation. Then it can be easily compiled to human readable docs by jsDoc tools. The most interesting part, is that you can:

Then you can use proper tools to check code before a build. Or even use data type information about JavaScript variables to provide enhanced optimization with Google Closure Compiler. Nevertheless when using external libraries, you’ll have to write definitions for them (see: @external). Also quite an issue is the fact that you have to add a lot of bloat to code — huge blocks of comments. It breaks the flow.

Flow

Facebook Flow is a static type checker, designed to find type errors in JavaScript programs. Actually it’s a superset of JavaScript, which means that a valid JavaScript is also a valid Flow annotated JavaScript. But not the reverse. JS file, when annotated with flow, will not run in browser. But its file extension is still .js . May be quite misleading, right?

What really shines in Flow, is that its type inference is designed in a way that helps a developer to gradually evolve JavaScript code into typed code and to easily mix statically and dynamically typed code. It is so forgiving that it makes transition to Flow almost totally painless. See five simple examples of Flow in action.

It also supports ES6 classes and destructuring, generic types, polymorphic classes, not concrete definitions (interfaces), .jsx React files… and much more. All it makes Flow a mature static type checker. I’d go further then it’s creators and call it a language.

TypeScript

Microsoft TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. As with both previous type checkers, you can start with JavaScript files that you already have. Just change their extension to .ts . I consider this a good idea, because TS code — same as with Flow — may not be a valid JS.

Converting bigger apps from JS may be a bit painful. TS uses implicit any type (just like Flow) but its type inference is different (more strict?):

Источник

Оцените статью