Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Just Use Any: js.la Edition

Lauren Tan
January 30, 2020

Just Use Any: js.la Edition

TypeScript has won the hearts and minds of programmers all around the world. Unfortunately, your deadlines are due yesterday, your boss is unconvinced, and your team remains skeptical. What's a TypeScript enthusiast to do? Join me on a journey of self-discovery: we'll learn what it means to lead by influence and level up our effectiveness as engineers. Then, an exploration of the value to engineering and business brought about by type systems (with some math to prove it). To tie it all together, we'll explore this through the lens of real world stories from Netflix, where we use TypeScript to modernize filmmaking.

Lauren Tan

January 30, 2020
Tweet

More Decks by Lauren Tan

Other Decks in Programming

Transcript

  1. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA Just Use Any Lauren Tan (she/her) PRESENTED BY unknown
  2. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA type Spiderman SKIP INTRO
  3. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA Type systems at ${work}.
  4. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA https://jobs.netflix.com/
  5. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA Type Systems at Netflix Studio UI. We're hiring UI Engineers in LA!
  6. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA Studio UI Foundations. react redux* Apollo GraphQL TypeScript gatsby/Next.js lerna yarn ??? Top secret stuff Designed by Sophinie Som https://jobs.netflix.com/jobs/870589 (my awesome team)
  7. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA TypeScript. GraphQL. gRPC. JVM.
  8. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA Making the case for typed JavaScript at Netflix.
  9. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA 1. Improve developer productivity. Making the case for typed JavaScript at Netflix.
  10. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA 2. Reduce bugs. Making the case for typed JavaScript at Netflix.
  11. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA 3. Performance*. Making the case for typed JavaScript at Netflix.
  12. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA https://mrale.ph/blog/2015/01/11/whats-up-with-monomorphism.html
  13. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA 4. End to end type safety. Making the case for typed JavaScript at Netflix.
  14. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA We also considered the risks of adopting typed JavaScript. Making the case for typed JavaScript at Netflix.
  15. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA TypeScript checked most of those boxes. Making the case for typed JavaScript at Netflix.
  16. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA Building a community.
  17. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA MY CODEBASE AFTER 3.7 LANDS yay!?.optional!?.chaining
  18. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA • Matt Greer - Type Widening • Ryan Anklam - TVUI's Experience with TypeScript Tim Branyen - Experience Using TypeScript in AppDirectory • Jordan Gensler - How To Type Everything • Danny Cochran - TypeScript with Maple • Randy Wenas - TS at Employee Apps • Emily Dobervich - TypeScript is just JavaScript • Young Min Kim - Using TypeScript Today Passionate TypeScript users at Netflix. Building a community.
  19. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA "Prefer statically typed [!!...] for better developer productivity"
  20. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA TypeScript. GraphQL. gRPC. JVM.
  21. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA Djikstra, supposedly "If debugging is the process of removing software bugs, then programming must be the process of putting them in."
  22. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA "A type system is a tractable syntactic method for proving the absence of certain program behaviors by classifying phrases according to the kinds of values they compute." Types and Programming Languages, Benjamin C. Pierce
  23. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA How many ways can this program fail?
  24. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA const half = x !=> x / 2;
  25. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA const TEST_CASES = [ null, undefined, Symbol(1), 10, '10', 'hello world', { name: 'Lauren' }, [1, 2, 3], x !=> x * x ];
  26. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA TEST_CASES.map(testValue !=> { return { result: half(testValue), test: testValue.toString() } });
  27. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA TEST_CASES.map(testValue !=> { return { result: half(testValue), test: testValue.toString() } ^^^^^^^^^^ });
  28. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA Spend less time debugging, and more time writing code.
  29. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA const TEST_CASES = [ null, !// Uncaught TypeError undefined, !// Uncaught TypeError Symbol(1), !// Uncaught TypeError 10, !// 5 '10', !// 5 'hello world', !// NaN { name: 'Lauren' }, !// NaN [1, 2, 3], !// NaN x !=> x * x !// NaN ];
  30. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA How many ways can this program fail? (Infinity)
  31. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA const half = (x: number) !=> x / 2;
  32. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA How many ways can this program fail (at compile time)?
  33. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA What are types anyway?
  34. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA A type is the set of possible values for a term.
  35. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA string type T1 = string '中⽂' 'español' '⽇本語' 'js.la' '2019' '✌'
  36. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA number number type T2 = number 2019 NaN Infinity 123.45 0x11 123e-1
  37. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA type T3 = string | number '中⽂' 'español' '⽇本語' 'js.la' '2019' '✌' 2019 NaN Infinity 123.45 0x11 123e-1 number string
  38. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA Why should I care about the cardinality of a type? cardinality · number of elements of the set
  39. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA number type T4 = 'TSConf' | 'dotJS' | 'React Rally' Cardinality: 3 'TSConf' 'dotJS' 'React Rally'
  40. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA number type Option<A> = None | Some<A> Cardinality: 2 None Some<Person> https://github.com/gcanti/fp-ts
  41. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA number Cardinality: Infinity undefined null number string symbol array object type T5 = unknown
  42. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA type T5 = unknown *slaps roof of typescript* this bad type can fit so many types in it
  43. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA When we restrict what we can do, RUNAR BJARNASON it's easier to understand what we can do. https://youtu.be/GqmsQeSzMdw
  44. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA Being precise helps TypeScript help you.
  45. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA I had no idea how interpreters or compilers work. So I decided to build one. github.com/poteto/boba-js
  46. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA !// Integers & arithmetic expressions!!... let version = 1 + (50 / 2) - (8 * 3); !// !!... and strings let name = "The Monkey programming language"; !// !!... booleans let isMonkeyFastNow = true; !// !!... arrays & hash maps let people = [{"name": "Anna", "age": 24}, {"name": "Bob", "age": 99}]; monkeylang.org
  47. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA !// User-defined functions!!... let getName = fn(person) { person["name"]; }; getName(people[0]); !// !=> "Anna" getName(people[1]); !// !=> "Bob" !// and built-in functions puts(len(people)) !// prints: 2
  48. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA let fibonacci = fn(x) { if (x !== 0) { 0 } else { if (x !== 1) { return 1; } else { fibonacci(x - 1) + fibonacci(x - 2); } } };
  49. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA !// `newAdder` returns a closure that makes use of the free variables `a` and `b`: let newAdder = fn(a, b) { fn(c) { a + b + c }; }; !// This constructs a new `adder` function: let adder = newAdder(1, 2); adder(8); !// !=> 11
  50. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA Lex Parse Evaluate Simple interpreter architecture.
  51. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA Lex Parse Evaluate Simple interpreter architecture.
  52. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA let add = fn(x, y) { x + y; };
  53. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA let add = fn(x, y) { x + y; };
  54. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA [ { type: TokenType.LET, literal: 'let' }, { type: TokenType.IDENT, literal: 'add' }, { type: TokenType.ASSIGN, literal: '=' }, { type: TokenType.FUNCTION, literal: 'fn' }, { type: TokenType.LPAREN, literal: '(' }, { type: TokenType.IDENT, literal: 'x' }, { type: TokenType.COMMA, literal: ',' }, { type: TokenType.IDENT, literal: 'y' }, { type: TokenType.RPAREN, literal: ')' }, { type: TokenType.LBRACE, literal: '{' }, { type: TokenType.IDENT, literal: 'x' }, { type: TokenType.PLUS, literal: '+' }, { type: TokenType.IDENT, literal: 'y' }, { type: TokenType.SEMICOLON, literal: ';' }, { type: TokenType.RBRACE, literal: '}' }, { type: TokenType.SEMICOLON, literal: ';' }, { type: TokenType.EOF, literal: '' }, ];
  55. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA export type LiteralType = string; export type Token = { type: TokenType; literal: LiteralType; };
  56. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA Lex Parse Evaluate Simple interpreter architecture.
  57. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA [ LetStatement { token: { type: 'LET', literal: 'let' }, name: Identifier { token: [Object], value: 'add' }, value: FunctionLiteral { token: [Object], parameters: [Array], body: [BlockStatement] } } ]
  58. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA export type BooleanLiteralToken = { type: TokenType.TRUE | TokenType.FALSE; literal: LiteralType; }; export default class BooleanLiteral implements Expression { constructor(public token: BooleanLiteralToken, public value: boolean) {} expressionNode() { /** snip **/ } tokenLiteral() { /** snip **/ } toString() { /** snip **/ } }
  59. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA export type BooleanLiteralToken = { type: TokenType.TRUE | TokenType.FALSE; literal: LiteralType; }; export default class BooleanLiteral implements Expression { constructor(public token: BooleanLiteralToken, public value: boolean) {} expressionNode() { /** snip **/ } tokenLiteral() { /** snip **/ } toString() { /** snip **/ } } We only want to create BooleanLiteralASTNodes if we encounter a boolean literal Token (true | false)
  60. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA !(true !== true); currToken
  61. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA !(true !== true); currToken
  62. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA !(true !== true); currToken
  63. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA export type LiteralType = string; export type Token = { type: TokenType; literal: LiteralType; };
  64. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA export const enum TokenType { ILLEGAL = 'ILLEGAL', EOF = 'EOF', !// Identifiers + Literals IDENT = 'IDENT', INT = 'INT', !// Operators ASSIGN = '=', PLUS = '+', MINUS = '-', BANG = '!', ASTERISK = '*', SLASH = '/', LT = '<', GT = '>', EQ = '!==', NOT_EQ = '!!=', !// Delimiters COMMA = ',', SEMICOLON = ';', LPAREN = '(', RPAREN = ')', LBRACE = '{', RBRACE = '}', !// Keywords FUNCTION = 'FUNCTION', LET = 'LET', TRUE = 'TRUE', FALSE = 'FALSE', IF = 'IF', ELSE = 'ELSE', RETURN = 'RETURN', } 27 types of Tokens.
  65. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA export default function parseBoolean(this: Parser): Expression { return new BooleanLiteral(this.currToken, !/* !!... !*/); !// ^^^^^^^^^^^^^^ !// Argument of type 'Token' is not assignable to parameter of type !// 'BooleanLiteralToken'. !// Types of property 'type' are incompatible. !// Type 'TokenType' is not assignable to type !// 'TokenType.TRUE | TokenType.FALSE'.ts(2345) } this.currToken could be *any* token!
  66. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA export default function assertTokenType<T extends TokenType>( token: Token, !!...assertedTokenTypes: T[] ): asserts token is { type: T; literal: LiteralType } { const satisfiesAssertion = assertedTokenTypes.some( type !=> type !!=== token.type ); if (!satisfiesAssertion) { throw new AssertionError({ message: `Token type is not: ${assertedTokenTypes.join(' OR ')}`, }); } }
  67. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA export default function assertTokenType<T extends TokenType>( token: Token, !!...assertedTokenTypes: T[] ): asserts token is { type: T; literal: LiteralType } { const satisfiesAssertion = assertedTokenTypes.some( type !=> type !!=== token.type ); if (!satisfiesAssertion) { throw new AssertionError({ message: `Token type is not: ${assertedTokenTypes.join(' OR ')}`, }); } }
  68. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA export default function parseBoolean(this: Parser): Expression { assertTokenType(this.currToken, TokenType.TRUE, TokenType.FALSE) return new BooleanLiteral(this.currToken, !/* !!... !*/); !// ^^^^^^^^^^^^^^ !// (property) Parser.currToken: { !// type: TokenType.TRUE | TokenType.FALSE; !// literal: string; !// } } ✅ this.currToken MUST be of type TokenType.TRUE | TokenType.FALSE
  69. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA export default function hasOwnProperty<T>( obj: T, key: PropertyKey ): key is keyof T { return Object.prototype.hasOwnProperty.call(obj, key); }
  70. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA export default function hasOwnProperty<T>( obj: T, key: PropertyKey ): key is keyof T { return Object.prototype.hasOwnProperty.call(obj, key); }
  71. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA export function lookupIdentifier(ident: string) { if (hasOwnProperty(KEYWORDS, ident)) { return KEYWORDS[ident]; } return TokenType.IDENT; }
  72. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA export function lookupIdentifier(ident: string) { if (hasOwnProperty(KEYWORDS, ident)) { return KEYWORDS[ident]; } return TokenType.IDENT; } ident starts out as a string. Cardinality is infinite.
  73. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA const KEYWORDS = { fn: TokenType.FUNCTION, let: TokenType.LET, true: TokenType.TRUE, false: TokenType.FALSE, if: TokenType.IF, else: TokenType.ELSE, return: TokenType.RETURN, } as const; hasOwnProperty(KEYWORDS, ident)
  74. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA export function lookupIdentifier(ident: string) { if (hasOwnProperty(KEYWORDS, ident)) { return KEYWORDS[ident]; !// ^^^^^ !// (parameter) ident: !// | "fn" !// | "let" !// | "true" !// | "false" !// | "if" !// | "else" !// | "return" } return TokenType.IDENT; } ident is now a string literal, with a cardinality of 7.
  75. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA !// inferred by TypeScript function lookupIdentifier( ident: string ): | TokenType.IDENT | TokenType.FUNCTION | TokenType.LET | TokenType.TRUE | TokenType.FALSE | TokenType.IF | TokenType.ELSE | TokenType.RETURN;
  76. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA 1. Improve developer productivity. Making the case for typed JavaScript at Netflix.
  77. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA 2. Reduce bugs. Making the case for typed JavaScript at Netflix.
  78. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA 3. Performance*. Making the case for typed JavaScript at Netflix.
  79. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA 4. End to end type safety. Making the case for typed JavaScript at Netflix.
  80. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA Spend less time debugging, and more time writing code.
  81. ! sugarpirate_ " poteto Just Use Any js.la 2020, Los

    Angeles, CA A type is the set of possible values for a term. cardinality · number of elements of the set