Slide 1

Slide 1 text

A Quick Tour of Built-In Utility Types in TypeScript (And Also React)

Slide 2

Slide 2 text

keyof type ObjectLiteralType = { first: 1, second: 2, }; // %inferred-type: "first" | "second" type Result = keyof ObjectLiteralType; // (A)

Slide 3

Slide 3 text

Getting the type of a single key in an object Use the index operator. type Obj = { 0: 'a', 1: 'b', prop0: 'c', prop1: 'd', }; // %inferred-type: "c" type Result0 = Obj['prop0']; // %inferred-type: "a" | "b" type Result1 = Obj[0 | 1]; // %inferred-type: "c" | "d" type Result2 = Obj['prop0' | 'prop1'];

Slide 4

Slide 4 text

What about getting the values? It's not as clean, but it'll work. type Obj = { a: 'A'; b: 'B'; c: number } // %inferred-type: number | "A" | "B" type Values = Obj[keyof Obj]

Slide 5

Slide 5 text

Unions type A = 'a' | 'b' | 'c'; type B = 'b' | 'c' | 'd'; // %inferred-type: "a" | "b" | "c" | "d" type Union = A | B;

Slide 6

Slide 6 text

Unions with Objects type ObjectTypeA = { propA: bigint, sharedProp: string, } type ObjectTypeB = { propB: boolean, sharedProp: string, } type Union = ObjectTypeA | ObjectTypeB; You have to check for anything that is not shared between both.

Slide 7

Slide 7 text

Intersections This is useful when trying to combine the props that you're going to use for a React component, just sayin'. type A = 'a' | 'b' | 'c'; type B = 'b' | 'c' | 'd'; // %inferred-type: "b" | "c" type Intersection = A & B; Conditionals! Ternaries only. type Wrap = T extends { length: number } ? [T] : T;

Slide 8

Slide 8 text

Slide 9

Slide 9 text

Exclude Takes stuff out of a union. It's built into TypeScript, but here is also what it would look like if you wanted to implement it yourself. type Exclude = T extends U ? never : T; // %inferred-type: 1 | 3 type Result0 = Exclude<1 | 2 | 3, 2>; // %inferred-type: "a" | "b" type Result1 = Exclude<1 | 'a' | 2 | 'b', number>; // %inferred-type: "a" | 2 type Result2 = Exclude<1 | 'a' | 2 | 'b', 1 | 'b' | 'c'>;

Slide 10

Slide 10 text

Extract The opposite of Exclude. type Extract = T extends U ? T : never; // %inferred-type: 1 | 2 type Result1 = Extract<1 | 'a' | 2 | 'b', number>; // %inferred-type: 1 | "b" type Result2 = Extract<1 | 'a' | 2 | 'b', 1 | 'b' | 'c'>;

Slide 11

Slide 11 text

Objects type ObjectWithAKey = { a: string }; You can also define a type for keys as well. type ObjectWithStringKeys = { [key: string]: number };

Slide 12

Slide 12 text

Objects You can iterate over a union if you want. // %inferred-type: { a: number; b: number; c: number; } type Result = { };

Slide 13

Slide 13 text

ReturnType type BasicMath = (a: number, b: number) => number; // %inferred-type: number type BasicMathReturn = ReturnType

Slide 14

Slide 14 text

Pick Omit Literally the opposite of Pick type ObjectLiteralType = { eeny: 1, meeny: 2, miny: 3, moe: 4, }; // %inferred-type: { meeny: 2; moe: 4; } type Result = Pick;

Slide 15

Slide 15 text

Omit Literally the opposite of Pick type ObjectLiteralType = { eeny: 1, meeny: 2, miny: 3, moe: 4, }; // %inferred-type: { meeny: 2; moe: 4; } type Result = Omit;

Slide 16

Slide 16 text

String Manipulation Utilities type UppercaseWes = Uppercase<'wes'>; type LowercaseWes = Lowercase<'Wes'>; type CapitalizeWes = Capitalize<'wes'>; type UncapitalizeWes = Uncapitalize<'Wes'>;

Slide 17

Slide 17 text

React.HTMLProps Type representing Props of specified HTML Element - for extending HTML Elements const Input: React.FC> = props => { ... }

Slide 18

Slide 18 text

React.ComponentProps We'll use this one in the very next exercise—just sayin'. type MyComponentProps = React.ComponentProps;

Slide 19

Slide 19 text

Generic List Component import * as React from 'react'; export interface GenericListProps { items: T[]; itemRenderer: (item: T) => JSX.Element; } export class GenericList extends React.Component, {}> { render() { const { items, itemRenderer } = this.props; return (
{items.map(itemRenderer)}
); } }