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

TypeScript and React Utility Types

Steve Kinney
March 26, 2021
150

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 Slide

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

    View 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 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 Slide

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

    View 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 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 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 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 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 Slide

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

    View Slide

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

    View Slide

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

    View 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 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 Slide

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

    View Slide

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

    View Slide

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

    View 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 Slide