Skip to content

Instantly share code, notes, and snippets.

@overthemike
Created April 25, 2025 04:21
Show Gist options
  • Save overthemike/7f9100405b7cdc063aaff4dcc6b820e7 to your computer and use it in GitHub Desktop.
Save overthemike/7f9100405b7cdc063aaff4dcc6b820e7 to your computer and use it in GitHub Desktop.
runtime type narrowing

typeof operator

const processValue = (value: string | number) => {
  if (typeof value === 'string') {
    // TypeScript knows 'value' is a string here
    return value.toUpperCase();
  } else {
    // TypeScript knows 'value' is a number here
    return value.toFixed(2);
  }
}

Type Guards

interface User {
  name: sring
  role: string
}
interface Admin {
  name: string
  privs: string[]
}

const isAdmin(user: User | Admin): user is Admin {
  return 'privs' in user
}

const processUser = (person: User | Admin) => {
  if (isAdmin(person)) {
    // TypeScript knows 'person' is an Admin here
    console.log(person.privileges);
  } else {
    // TypeScript knows 'person' is a User here
    console.log(person.role);
  }
}

Descriminated unions (like the first example in the gist). Here's a pretty good example of a different one. "Rails Errors" - from: https://gist.github.com/t3dotgg/a486c4ae66d32bf17c09c73609dacc5b

type Success<T> = {
  data: T
  error: null
}

type Failure<E> = {
  data: null
  error: E
}

// if the object property types match success, return a success, otherwise return a failure type
type Result<T, E = Error> = Success<T> | Failure<E>

const tryCatch = async <T, E = Error> (
  promise: Promise<T>
): Promise<Result<T, E>> {
  try {
    const { data } = await promise
    return { data, error: null }
  } catch (error) {
    return { data: null, error: error as E}
  }
}

Type Predicates

function hasProperty<T, K extends string>(
  obj: T, 
  prop: K
): obj is T & Record<K, unknown> {
  return Object.prototype.hasOwnProperty.call(obj, prop);
}

function processObject(obj: unknown) {
  if (hasProperty(obj, 'name')) {
    // TypeScript knows obj has a 'name' property
    console.log(obj.name);
  }
}

And others...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment