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

TypeScript and React Utility Types

Avatar for Steve Kinney Steve Kinney
March 26, 2021
180

TypeScript and React Utility Types

Avatar for Steve Kinney

Steve Kinney

March 26, 2021
Tweet

Transcript

  1. keyof type ObjectLiteralType = { first: 1, second: 2, };

    // %inferred-type: "first" | "second" type Result = keyof ObjectLiteralType; // (A)
  2. 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'];
  3. 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]
  4. Unions type A = 'a' | 'b' | 'c'; type

    B = 'b' | 'c' | 'd'; // %inferred-type: "a" | "b" | "c" | "d" type Union = A | B;
  5. 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.
  6. 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> = T extends { length: number } ? [T] : T;
  7. 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, B> = 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<number, 123>;
  8. 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, U> = 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'>;
  9. Extract The opposite of Exclude. type Extract<T, U> = 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'>;
  10. Objects type ObjectWithAKey = { a: string }; You can

    also define a type for keys as well. type ObjectWithStringKeys = { [key: string]: number };
  11. Objects You can iterate over a union if you want.

    // %inferred-type: { a: number; b: number; c: number; } type Result = { };
  12. ReturnType type BasicMath = (a: number, b: number) => number;

    // %inferred-type: number type BasicMathReturn = ReturnType<BasicMath>
  13. 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<ObjectLiteralType, 'meeny' | 'moe'>;
  14. 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<ObjectLiteralType, 'eeny' | 'miny'>;
  15. String Manipulation Utilities type UppercaseWes = Uppercase<'wes'>; type LowercaseWes =

    Lowercase<'Wes'>; type CapitalizeWes = Capitalize<'wes'>; type UncapitalizeWes = Uncapitalize<'Wes'>;
  16. React.HTMLProps<HTMLXXXElement> Type representing Props of specified HTML Element - for

    extending HTML Elements const Input: React.FC<Props & React.HTMLProps<HTMLInputElement>> = props => { ... } <Input about={...} accept={...} alt={...} ... />
  17. React.ComponentProps<typeof XXX> We'll use this one in the very next

    exercise—just sayin'. type MyComponentProps = React.ComponentProps<typeof MyComponent>;
  18. Generic List Component import * as React from 'react'; export

    interface GenericListProps<T> { items: T[]; itemRenderer: (item: T) => JSX.Element; } export class GenericList<T> extends React.Component<GenericListProps<T>, {}> { render() { const { items, itemRenderer } = this.props; return ( <div> {items.map(itemRenderer)} </div> ); } }