Skip to content

Instantly share code, notes, and snippets.

@EddiG
Last active October 24, 2022 12:56
Show Gist options
  • Save EddiG/385f2e37f151d1a8cb0e4ab345b5bba8 to your computer and use it in GitHub Desktop.
Save EddiG/385f2e37f151d1a8cb0e4ab345b5bba8 to your computer and use it in GitHub Desktop.
TypeScript tips and tricks

TypeScript

Tools

  • zod - TypeScript-first schema validation with static type inference
  • tRPC - End-to-end typesafe APIs made easy
  • ts-toolbelt - Library of the TypeScript utilities

Generics

The List component with the generic type of item.

import React from "react";

interface ListProps<TItem> {
  items: TItem[];
  renderItem: (item: TItem) => React.ReactNode;
}

function List<TItem extends { id: React.Key }>(props: ListProps<TItem>) {
  const { items, renderItem } = props;

  return (
    <ul>
      {items.map((item) => (
        <li key={item.id}>{renderItem(item)}</li>
      ))}
    </ul>
  );
}

export default function App() {
  return (
    <div>
      <List
        items={[
          { id: 1, title: "One" },
          { id: 2, title: "Two" },
          { id: 3, title: "Three" }
        ]}
        renderItem={(item) => <h3>{item.title}</h3>}
      />
    </div>
  );
}

Get the typed value of the property of the arbitrary object.

const getDeepValue = <
  TObj,
  TKey1 extends keyof TObj,
  TKey2 extends keyof TObj[TKey1]
>(
  obj: TObj,
  key1: TKey1,
  key2: TKey2
) => {
  return obj[key1][key2];
};

const obj = {
  foo: {
    x: 1,
    b: "green"
  },
  bar: {
    y: 2,
    b: 0
  }
};

console.log(typeof getDeepValue(obj, "foo", "b")); // string
console.log(typeof getDeepValue(obj, "bar", "b")); // number

Restrict the possible argument type with the custom error message.

function compare <TArg>(
  a: TArg extends any[] ? `The Array can't be compared` : TArg, 
  b: TArg extends any[] ? `The Array can't be compared` : TArg
  ): boolean {
  return a === b;
}
compare('a', 'b') // false
compare([], []) // Error: The Array can't be compared

Convert object type into union of its properties

const initState = {
    email: "",
    password: "",
    subscribe: true,
}

type State = typeof initState

type StateUpdate = {
    [K in keyof State]: {
        [K2 in K]: State[K]
    }
}[keyof State]

// type StateUpdate = {
//     email: string;
// } | {
//     password: string;
// } | {
//     subscribe: boolean;
// }

const stateUpdate: StateUpdate = {
    subscribe: false,
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment