# Typing in JS ### Greg Hurrell ### [@wincent](https://github.com/wincent/)

Quiz πŸ“‹


          [1, NaN, 'foo'] + {a: true}
        

          πŸ‘‰πŸΌ  '1,NaN,foo[object Object]'
        

          10 / new Date()
        

          πŸ‘‰πŸΌ  6.454428654138961e-12
        

          Math.min('10', [3])
        

          πŸ‘‰πŸΌ  3
        

          true * false
        

          πŸ‘‰πŸΌ  0
        

My background

Or, why this is going to be a totally unbiased presentation

# Me using Flow.
# The Flow team.
# Should I use Flow? # Or TypeScript?

Yes

# Vanilla JS 🏚 * Dynamic. * Runs almost everywhere. * Turing complete! * Empires have been built on JavaScript... * ...but it can be hard to do really big, robust things with it.
# TypeScript πŸ”₯ * Modern JS designed with speed, productivity and safety in mind. * A big upgrade from untyped JavaScript.
# Flow πŸ”§ * Deadly serious type system for large codebases. * A big upgrade from untyped JavaScript.
# Type systems overview

Type annotations


          function increment(x: number): number {
            return x + 1;
          }

          increment(1); // OK
          increment(null); // Cannot call `increment` with `null`
        

Implicit return types


          function increment(x: number) {
            return x + 1;
          }

          increment(1); // OK
          increment(null); // Cannot call `increment` with `null`
        

Catching implementation errors


          function increment(x: number): string {
            return x + 1;
          }

          // Cannot return `x + 1` because
          // number is incompatible with string
        

Compiler output


          function increment(x) {
            return x + 1;
          }

          increment(1);
          increment(null);
        
# Benefits of type systems πŸŒˆπŸ¦„πŸ’˜ * Catch programming errors at build-time. * No runtime overhead. * Provide always-in-sync "documentation". * Power intelligent autocomplete, code navigation and other IDE features. * Enable type-assisted transforms and optimizations. * Complementary to test suites, which can therefore be made lighter. * Fail faster/earlier than test suites, saving expensive CI runs.
# Costs of type systems πŸ’ΈβŒ›οΈπŸŒ¨ * Impose new tooling requirements (linting, parsing, formatting etc). * Verbosity. * Learning curve.
# πŸ₯€ Is the juice worth the squeeze? πŸ‹
# Basic types | Type | Flow | TypeScript | | ---- | ---- | ---------- | | Boolean | `boolean` | `boolean` | | String | `string` | `string` | | Number | `number` | `number` | | Array of `T` | `Array<T>` | `T[]` | | Tuple | `[T, U]` | `[T, U]` |

          function process(input: Array<🍩>): Array<πŸ’©> {
            return input.map(eatDonut);
          }

        
# Complex and compound types | Type | Flow | TypeScript | | ---- | ---- | ---------- | | Union of `T` & `U` | `T | U` | `T | U` | | Intersection of `T` & `U` | `T & U` | `T & U` | | Function from `T` to `U` | `(T) => U` | `(t: T) => U` | | Object | `{}` | `object` | | Exact object | `{|a: T|}` | `{}` | | Map | `{[a] : T}` | `{[a: A]: T}` | | Enum | πŸ€” | `enum T {A, B}` |

          type Fruit = πŸ“ | 🍏 | πŸ‰;

          function eat(fruit: Fruit) {
            // Eat the fruit...
          }
        
# Special types | Type | Flow | TypeScript | | ---- | ---- | ---------- | | Unsafe | `any` | `any` | | Unknown | `mixed` | `unknown` | | Nothing | `void` | `void` | | Impossible | πŸ€” | `never` | | Nullable `T` | `?T` | `T | null | undefined` | | Type cast to `T` | `(a: T)` | `(a as T)` |

          function runEventLoop(): never {
            while (true) {
              processInput();
              updateGameState();
              renderFrame();
            }
          }
        
# "Imposter Syndrome" types | Type | Flow | TypeScript | | ---- | ---- | ---------- | | Bounded polymorphism | `<T: U>` | `<T extends U>` | | Covariance | `{+a: T}` | `{readonly a: T}` | | Contravariance | `{-a: T}` | πŸ€” |

          class FastFood<T: πŸ” | πŸ•> {
            _food: T;

            constructor(food: T) {
              this._food = food;
            }

            serve(): T {
              return this._food;
            }
          }
        
# Utility types | Type | Flow | TypeScript | | ---- | ---- | ---------- | | Non-nullable T | `$NonMaybeType<T>` | `NonNullable<T>` | | Return type of F | `$Call<typeof F>` | `ReturnType<typeof F>` | | Read-only T | `$ReadOnly<T>` | `Readonly<T>` | | Keys of T | `$Keys<T>` | `keyof T` | | Values of T | `$Values<T>` | `T[keyof T]` | | Property type (named) | `$PropertyType<T, 'prop'>` | `T['prop']` | | Property type (matching `K`) | `$ElementType<T, K>` | `T[K]` | | Exclusion (`T` without properties of `U`) | `$Rest<T, U>` | `Exclude<T, U>` |

          function nullthrows<T>(value: T): NonNullable<T> {
            if (value == null) {
              throw new Error('Unexpected null-ish value');
            }
            return value as NonNullable<T>;
          }
        
# Syntax | Syntax | Description | | -------------------- | ---- | | `type A = T`; | Type alias (`T` may be complex) | | `interface I { a: T; }` | Declaration that property `a` of type `T` exists in interface `I` | | `implements I` | Declaration that a class implements the `I` interface |
# Conditional types & type guards (TypeScript) | Annotation | Description | | -------------------- | ---- | | `T extends U ? X : Y` | `X` when `T` is assignable to `U`, and `Y` otherwise | | `var is T` | Type predicate that will be true whe `var` is of type `T` | `*` Flow implements type predicates too, using the `%checks` syntax.

          function isObject(value: unknown): value is object {
            return (
              value !== null &&
              Object.prototype.toString.call(value) === '[object Object]'
            );
          }
        
# But really, which should I use? πŸ€”
| TypeScript | Flow | | ---------- | ---- | | βœ… Thriving open-source community | ❌ Weaker engagement with community | | βœ… Great developer experience | πŸ†— Weaker out-of-the-box experience | | βœ… [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) | πŸ†— [flow-typed](https://github.com/flow-typed/flow-typed) | | βœ… Compatibility with Babel, Prettier, ESLint etc | βœ… Compatibility with Babel, Prettier, ESLint etc | | πŸ†— Support for React | βœ… First-class support for React | | πŸ†— Productive by default | βœ… Sound by default | | πŸ†— Works with huge repos | βœ… Crushes huge repos | | ❌ Microsoft is Evilβ„’ | ❌ Facebook is Evilβ„’ |
# I ❀️ Flow * [Flow linting](https://flow.org/en/docs/linting/): `sketchy-null`, `untyped-import` etc. * [`@flow strict`](https://flow.org/en/docs/strict/), and `strict-local`: per-file opt-in to stronger safety guarantees. * `flow lsp`: [Language Server Protocol](https://microsoft.github.io/language-server-protocol/) implementation.
# The reports of Flow's death are greatly exaggerated ☠ * Facebook is heavily invested in Flow despite a couple of open source projects migrating to TypeScript. * Facebook has *massive* React applications (thousands of components) in a monorepo containing millions of files, with a high % of Flow coverage. * Flow, which places great emphasis on soundness and speed at scale, is literally the only option that can possibly work for Facebook for the foreseeable future. * Open source projects at FB operate relatively independently, especially projects with large community involvement like Yarn, so their decision probably has nothing to do "corporate governance".
# Recommendations βœ… * Either system can be adopted gradually (per-package, and even per-file). * The cost of correcting a mistake is not prohibitive. * Flow is a "better" type system (soundness, Flow linter, strict mode etc). * But TypeScript is a *great* type system and getting better all the time. * There is benefit from adopting either system, but: # I recommend adopting TypeScript
# Example: Flow β†’ TypeScript * [github.com/wincent/js@b166b491c](https://github.com/wincent/js/commit/b166b491c4656fe34dcd5d3854c53c69c804378d)
# Other resources πŸ“— * Playgrounds: [Try Flow](https://flow.org/try/) and [TypeScript Playground](https://www.typescriptlang.org/play/) * [github.com/niieani/typescript-vs-flowtype](https://github.com/niieani/typescript-vs-flowtype) * [github.com/bcherny/flow-to-typescript](https://github.com/bcherny/flow-to-typescript) * [github.com/bcherny/undux](https://github.com/bcherny/undux) * [What the Flow team has been up to ](https://medium.com/flow-type/what-the-flow-team-has-been-up-to-54239c62004f) (28 January 2019)
# Resources for haters... πŸ“™ * [The TypeScript Tax](https://medium.com/javascript-scene/the-typescript-tax-132ff4cb175b) * [You Might Not Need TypeScript (or Static Types)](https://medium.com/javascript-scene/you-might-not-need-typescript-or-static-types-aa7cb670a77b) * [The ever-lasting strife of static vs dynamic typing β€” TypeScript won't help](https://habr.com/en/post/437844/) * [Why do people hate typescript?](https://www.quora.com/Why-do-people-hate-typescript) (Quora)
# Questions? * [greg@hurrell.net](mailto:greg@hurrell.net) βœ‰οΈ * [wincent.github.io/typing-in-js](https://wincent.github.io/typing-in-js)