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

TypeScript and React Utility Types

Steve Kinney
March 26, 2021
160

TypeScript and React Utility Types

Steve Kinney

March 26, 2021
Tweet

Transcript

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

    View full-size slide

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

    View full-size slide

  3. 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'];

    View full-size slide

  4. 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]

    View full-size slide

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

    View full-size slide

  6. 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.

    View full-size slide

  7. 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;

    View full-size slide

  8. Conditionals: Example
    There isn't much of a good reason for this one to exist,
    but it helps explain the syntax a bit, so here we are.
    type IsAssignableTo = A extends B ? true : false;
    // Type `123` is assignable to type `number`
    // %inferred-type: true
    type Result1 = IsAssignableTo<123, number>;
    // Type `number` is not assignable to type `123`
    // %inferred-type: false
    type Result2 = IsAssignableTo;

    View full-size slide

  9. 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'>;

    View full-size slide

  10. 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'>;

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  14. 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;

    View full-size slide

  15. 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;

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  19. 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)}

    );
    }
    }

    View full-size slide