Strong
Type-Checking
in JavaScript

First, vocabulary

Does JavaScript have types ?

  • 6 primitive types:
           string, number, undefined, null, boolean, symbol
     
  • anything else is a prototyped object
    types are abstract interfaces
    prototypes/classes are implementations of these types

YES

Does JavaScript

check types ?

OF COURSE

Is JavaScript typed ?

duh!

Static

done at compile-time
 

predictable type validity
 

machine-code optimizations
 

compiler instructions ?

Dynamic

done at run-time
 

 unpredictable type validity
 

variables can change types
 

program feature ?

vs

typing

typing

Does JavaScript have
static typing ?

Does JavaScript have
static typing ?

JavaScript has dynamic typing: a variable is not bound to a type

NOPE

var hi = "Hello !";
hi = 83110;
hi = ["H","e","l","l",0] ;
hi = function(){ alert("Hello !"); };

Does JavaScript have
strong type-checking ?

There is a never-ending argument about the definition of "strong" type-checking, but here are two common definitions:


1. the ability to bind an explicit type to a variable and guarantee        that this type always describe correctly the referenced data.

 

2. no lack of type safety due to looser typing rules,
     for example
implicit type coercion

HUM...

Strong type-checking

EXPECTATIONS vs REALITY

JavaScript handy footguns collection

Allowed in JS, forbidden in Python

Examples of

implicit boolean coercions

Implicit type coercion

Loose equality: == vs ===

JavaScript handy footguns collection

Variable reassignment

JavaScript handy footguns collection

const has become the
common recommended way
of declaring variables

Immutability is now highly valued
in JavaScript community

Does JavaScript have
strong type-checking ?

  1. Linters to add constraints and avoid footguns

NO, but...

maybe we can do something about it ?

You miss the point of static typing !

1. the ability to bind an explicit type to a variable and guarantee that this type always describe correctly the referenced data.

Strong Typing

The Case for
Static Type annotations

→ obvious solution: static type annotations

You can/must declare a variable with its type
Problem solved !

Actually, type-checking is not necessarily
the most interesting aspect of static type annotations

The documentative approach

JSDoc

Statically analyzable by most IDE, but a bit limited

We're in the era of compilers and front-end build tooling

  • Formatters
  • Linters
  • Babel
  • Bundlers
  • Minifiers / optimizers
     
  • next: Static type checkers ?

Since we already compile JS projects...

Flow

  • made by Facebook, released in 2014
  • adds optional static type annotations
    • possibily through JS comments,
      so your code stays 100% valid JS
  • can be added in your build chain next to your fav linter

TypeScript

  • open source language by Microsoft, released in 2012
  • want to be a typed superset of JavaScript that compile to JS
  • adds optional static type-checking
  • and a few other features:
    • interfaces
    • abstract classes
    • decorators
    • ...
  • based on Kazan Gitlab metrics,
    281 out of 1731 (~16%) web projects use TypeScript @WL
    This is huge !

TypeScript

Superset of JS = ascending compat = progressively adoptable

Ease of adoption is a huge popularity factor

But beware of the superset myth:

JS and TS evolve in parallel,
and the already existing deviations
ill widen over time.

 

example:  private fields are coming to JS

what about private keyword in TS ?

TypeScript real power:
static code analysis and type inference inside the IDE

The main argument in favor of TypeScript is the huge step up for Developer eXperience

TypeScript cons ?

  • optional typing = non-existent typing ?
    • devs are lazy or late
       
  • rely on a language and compiler owned by one company
     
  • external dependencies may not be written in TypeScript
    • *.d.ts and DefinitelyTyped project to the rescue
       
  • it may give the wrong ideas to main-Java developers
     
  • there is a TypeScript tax
    https://medium.com/javascript-scene/the-typescript-tax-132ff4cb175b

My take on TypeScript

  • Pretty cool, pretty good
  • Solid popularity and long-term support
    • not like Dart and CoffeeScript ;-)
  • But not a silver bullet
    • can slow you down on quick protos/small projects
    • type annotations are not that much useful outside logic/business parts of your app code
  • If your main goal is to prevent bugs, focus first on
    Test Driven Development and Code/Spec Reviews
     

Warning, personal opinion ahead !

An in-between approach

for TypeScript adoption

Definition files are *.d.ts files that allow you to provide type information for JavaScript code that is not statically typed.

Useful to add type annotations

to existing JS libs

Since TS 3.7, automatically generate .d.ts from JS files !

Does JavaScript have
strong type-checking ?

  1. Linters to add constraints and avoid footguns
  2. Static type checkers

NO, but...

maybe we can do something about it ?

Back to JavaScript

JavaScript has been designed for scripts and beginners:

  • high level primitive types
  • dynamic code eval in HTML
  • backwards compatibility

JS, why don't you have static typing ?

Dynamic languages are popular in large part because programmers can keep types latent in the code, with type checking done imperfectly (yet often more quickly and expressively) in the programmers’ heads and unit tests, and therefore programmers can do more with less code

I am not religious. I use static and dynamic languages all the time — and if there is one thing I’ve learned as a  programmer,
it is that there is never one right language for all jobs.

the Web, dynamic by nature ?

Unpredictable stuff for a front-end web dev:
(unpredictable = known at run-time)

Server responses

Browser support

(& bugs)

Client-side stored data

Platform

features

User inputs

This is data validation, not type-checking

TypeScript can't help you with that

How do I type-check all of this,

please ?

But it's basically the same problem...

Sorry, not a compiler problem,
more an applicative problem

You'll have to deal with it by yourself

Let's be honest
The usual way we deal with runtime errors
is to not really deal with them

if(!isValid(data)){ /* try to fix stuff */ }



try { } catch(error){
  alert(`Something bad happened: ${error}`)
}


window.onerror = pretendWeCareAboutUnexpectedErrors

Trying to fight runtime errors,
​one battle after another

  • Network management layer
    • handle network errors, no matter where and when
    • validate service calls inputs and outputs
  • Restrictive form/input validation library
    • Validate early, don't make assumptions
    • Autofix/autocomplete
  • Auto-validated and self-cleaning local storage
    • IndexedDB wrappers
    • Client/server synchronizations
  • Automatic polyfills/shims

All these dedicated tools are basically doing runtime validation

the ability to bind an explicit type to a variable and guarantee that this type always describe correctly the referenced data.

Strong Typing

Strong dynamic type-checking

→ what if we could do strong dynamic typing ?

  • Type errors would still be runtime errors,
    but explicit, descriptive, catched early errors
     
  • User-defined types could be shared and reused within the app
     
  • The type-check / validation step will have to be done on assignment and future mutations
  • my most "used for real" OS project so far
     
  • also the hardest to make
    (5 years old, rewritten 4 times)
     
  • not pretending to be a silver bullet neither

Making a generic
runtime validation library

Strong Dynamically Typed Object Modeling for JavaScript

the ability to bind an explicit type to a variable and guarantee that this type always describe correctly the referenced data.

Strong Typing

  1. define types ("models")



     
  2. bind models to data



     
  3. make this data observable and type-conservative

How it works

Types or Models ?

  • Strong dynamic typing = Continuous data validation ?



     
  • No clear distinction between type and value checking




     
  • Model validation can affect code logic

ObjectModel is more than just type-checking

  • Enumerations
  • Assertions
  • Default values
  • Null safe traversal
  • Constant/private properties
  • Composition/inheritance
  • Autocasting
  • ...

See http://objectmodel.js.org/ docs for more information

ObjectModel pros

  • Descriptive error messages, pointing to the initial problem, not its consequences
  • Continuous data validation as part of the dev process: faster debugging
  • Global or per-feature strategies for form validation, network invalid responses, local storage purge...

ObjectModel cons

  • Perf penalty on data with very frequent mutations
    (avoid on data mutating more than 100 times per second)
  • Require browser support for ES6 Proxies:
    (Edge 14+, Firefox 47+, Chrome 50+, Safari 10+, Node 6.0+)

Does JavaScript have
strong type-checking ?

  1. Linters to add constraints and avoid footguns
  2. Static type checkers
  3. Strong dynamically typed object modeling

NO, but...

maybe we can do something about it ?

Which is better ?
Static or dynamic typing ?

USE BOTH

Recommendation:

Static anotations
in core logic

Dynamic modeling
on external interfaces

they address different issues

Conclusion

  • Don't be too dogmatic about type-checking.
    Context matters a lot when discussing type theory
     
  • Static analysis is great ! Type-checking is not the most appealing feature of TypeScript
     
  • Same for strong dynamic modeling: it brings much more features to the table than just type safety
     
  • Both static and dynamic typing are useful and often under-exploited in current JS landscape

that's all folks

thanks !

Strong Typing in JavaScript

By sylvainpv

Strong Typing in JavaScript

  • 1,525