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

TypeScript and React Utility Types

Steve Kinney
March 26, 2021
170

TypeScript and React Utility Types

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> ); } }