logo

My TypeScript cheatsheet

keyof

The keyof operator takes an object type and produces a string or numeric literal union of its keys.

For example, it can be used to create a more readable and maintainable type for an object:

ts
interface IUser {
  name: string
  age: number
}

type UserKeys = keyof IUser // "name" | "age"

Use the keyof operator to create more type-safe functions

ts
function getValue<T, K extends keyof T>(obj: T, key: K) {
  return obj[key]
}
const user: IUser = { name: 'Mike', age: 18 }
getValue(user, 'name') // 'Mike'
getValue(user, 'gender') // Compile-time error: "gender" is not a key of IUser

Exclude

Exclude<T, U> removes members of a union that are assignable to U. To remove properties from an object type, use Omit<T, Keys>.

ts
interface IUser {
  name: string
  age: number
}
type UserWithoutAge = Omit<IUser, 'age'> // { name: string }

type T0 = Exclude<'a' | 'b' | 'c', 'a'> // "b" | "c"

Official Exclude implementation

ts
type Exclude<T, U> = T extends U ? never : T

ReturnType

Grab the type returned from a function

ts
const sum = (a: number, b: number) => a + b

type SumResult = ReturnType<typeof sum> // number

Awaited

Awaited<T> unwraps a promise type, including nested promises.

ts
const sumAsync = async (a: number, b: number) => a + b

type SumResult = Awaited<ReturnType<typeof sumAsync>> // number

Generic

ts
function toLabelValue<T, LabelKey extends keyof T, ValueKey extends keyof T>(
  labelKey: LabelKey,
  valueKey: ValueKey,
  obj: T
) {
  return {
    label: obj[labelKey],
    value: obj[valueKey],
  }
}

interface Lib {
  id: number
  name: string
  isPublic: boolean
}

const lib = { id: 1, name: 'hi', isPublic: true }

// type: { label: string, value: number }
const labelValue = toLabelValue('name', 'id', lib)

TypeScript utility-type reference