React ❤️ TypeScript


What is TypeScript?

JS + Static Types

  • Not having to worry about using properties wrongly
  • Compile-Time checking
  • Better Autocompletion
  • Types exist at compile time only

const div = (a, b) => a / b; div(4, 2) === 2 div(4, "abc") === NaN

const div = (a: number, b: number): number => a / b; div(4, 2) === 2 div(4, "abc") // ⚡️ abc is not of type `number`

const div = (a: number, b: number) => a / b; div(4, 2) === 2 div(4, "abc") // ⚡️ abc is not of type `number`

JS ⊆ TS

➡️ gradual adoption


Simple Types

  • number
  • string
  • boolean
  • Literals
    • true & false
    • String literals (like "bla")
    • Number literals (like 1, 2)

Records & Interfaces

interface SomeType { member1: boolean; member2: HTMLElement; member3: string; member4: "bla"; }

Records & Interfaces

interface SomeType { member1: boolean; // can be true / false member2: HTMLElement; // can be any HTML element member3: string; // can be any string member4: "bla"; // can be *just* the string "bla" }

Union types

"This variable has all members of both types"

TypeA & TypeB, "TypeA and TypeB"


const a = { x: 123 }; // type { x: number } const b = { y: 456 }; // type { y: number }

const a = { x: 123 }; // type { x: number } const b = { y: 456 }; // type { y: number } const aAndB = { ...a, ...b };

const a = { x: 123 }; // type { x: number } const b = { y: 456 }; // type { y: number } // type { x: number, y: number } = typeof a & typeof b const aAndB = { ...a, ...b };

Intersection types

"This variable is either of type A or of type B"

TypeA | TypeB, "TypeA or TypeB"


const select = () => { const a = { variant: 'A', x: 123 }; const b = { variant: 'B', y: 456 }; };

const select = () => { // type { variant: 'A', x: number } const a = { variant: 'A', x: 123 }; // type { variant: 'B', y: number } const b = { variant: 'B', y: 456 }; };

const select = () => { // type { variant: 'A', x: number } const a = { variant: 'A', x: 123 }; // type { variant: 'B', y: number } const b = { variant: 'B', y: 456 }; return Math.random() > 0.5 ? a : b; };

// returns either a or b, so: // typeof a | typeof b = // | { variant: 'A', x: number } // | { variant: 'B', y: number } const select = () => { // type { variant: 'A', x: number } const a = { variant: 'A', x: 123 }; // type { variant: 'B', y: number } const b = { variant: 'B', y: 456 }; return Math.random() > 0.5 ? a : b; };

Intersection narrowing

type A = typeof a = { variant: 'A', x: number }; type B = typeof b = { variant: 'B', y: number };

const getStr = (item: A | B): string => { };

const getStr = (item: A | B): string => { switch (item.variant) { case "A": case "B": } };

const getStr = (item: A | B): string => { switch (item.variant) { case "A": console.log(item.x); // ✅ case "B": } };

const getStr = (item: A | B): string => { switch (item.variant) { case "A": console.log(item.x); // ✅ case "B": console.log(item.y); // ✅ } };

const getStr = (item: A | B): string => { switch (item.variant) { case "A": console.log(item.x); // ✅ console.log(item.y); // ⚡️ case "B": console.log(item.y); // ✅ console.log(item.x); // ⚡️ } };

const getStr = (item: A | B): string => { switch (item.variant) { case "A": console.log(item.x); // ✅ console.log(item.y); // ⚡️ return String(item.x); case "B": console.log(item.y); // ✅ console.log(item.x); // ⚡️ return String(item.y); } };

const getStr = (item: A | B): string => { switch (item.variant) { case "A": console.log(item.x); // ✅ console.log(item.y); // ⚡️ return String(item.x); case "B": console.log(item.y); // ✅ console.log(item.x); // ⚡️ return String(item.y); // no `default:`-case, but that's okay because // the switch is exhaustive! } };

Strict Mode

  • tsc can treat null and undefined as concrete types
  • Every other type then becomes non-nullable
    • string !== string | null
  • Very powerful when combined with intersection types
    • Forces programmer to handle null-case
    • Completely eliminates null-errors 🎉

const trim = (param: string | null) => { return param.trim(); // ⚡️ param can be `null` if (!param) { // this branch must diverge return ''; } return param.trim(); // ✅ no complaints from tsc };

TypeScript + React?

  1. Safe passing of props
  2. Handle state correctly

Creating a new React App in TypeScript

$ npx create-react-app my-app --typescript
$ yarn create react-app my-app --typescript

Demo


Conclusion

  • Less bugs & increased productivity
  • Fluent & gradual transition
  • Easy initial setup
  • Great documentation, good for beginners

Further Reading

Select a repo