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 ?
- 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
- possibily through JS comments,
- 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
- 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
- *.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 ?
- Linters to add constraints and avoid footguns
- 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
- Babel preset-env
- https://polyfill.io/
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
- define types ("models")
- bind models to data
- 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 ?
- Linters to add constraints and avoid footguns
- Static type checkers
- 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,499