🗂️ Typescript Cheat Sheet

A collection of useful typescript utilities


Function Overload

In Next.js you can call server functions from the client side directly, however, the type hints may mislead you and cause error.

For example:

type FormData = {
  name: string
  age: string
}
export function serverAction(data: FormData) {
  const { name, age } = data
}

We cannot trust what the client submits, the name or age prop may not exist in the real world, we should validate the data first, so change that to:

function validate(data: unknown): FormData {
  // validates data here
  ...
  return data as FormData
}
export function serverAction(data: FormData) {
  const validData = validate(data)
  const { name, age } = data // woops, should be validData here
}

Declaring data as FormData type may not be a good idea, since there is no error hints when you accidentally use data.name or data.age, so you should change its type to unknown

export function serverAction(data: unknown) {
  const validData = validate(data)
  // const { name, age } = data, this will show ts error
  const { name, age } = validData
}

But in this case, we lose type hints on the client side, a better solution is to add another function declaration for the client side using overload.

The final version:

type FormData = {
  name: string
  age: string
}
export function serverAction(data: FormData): void
export function serverAction(data: unknown) {
  const validData = validate(data)
  const { name, age } = validData
}
function validate(data: unknown): FormData {
  // validates data here
  ...
  return data as FormData
}

DistributiveOmit

type DistributiveOmit<T, K extends keyof T> = T extends unknown
  ? Omit<T, K>
  : never

Why not just use Omit?

interface A {
  id: string
  label: string
  a: string
}
interface B {
  id: string
  label: string
  b: string
}
type C = A | B
type D = Omit<C, 'id'> // can not get correct type, same as Omit<A, 'id'>

ArrayElement

type ArrayElement<T> = T extends readonly (infer E)[] ? E : never

Or simplified version

const chars = ['a', 'b', 'c']
const char: (typeof chars)[number] = 's'

Extend Third-party Module Interface

global.d.ts
import 'module-name'
declare module 'module-name' {
  export interface ToBeExtended {
    prop: unknown
  }
}