Getting Started

Installation

Get safeids into your TypeScript project in under two minutes.

Install the package

safeids has no runtime dependencies. It works with any TypeScript project — Next.js, Remix, Node, tRPC, Prisma, you name it.

npmpnpmyarnbun
npm install safeids
⚠️ Requires TypeScript 4.7+ and strict: true in your tsconfig. The strict flag is what makes branded types incompatible with each other.

Your first branded ID

Create a src/types/ids.ts file and define your domain entities:

src/types/ids.ts
import { brand, createId } from 'safeids'

// 1. Declare the branded type
export type UserId  = brand<string, 'UserId'>
export type OrderId = brand<string, 'OrderId'>

// 2. Create a typed ID generator for each entity
export const newUserId  = () => createId<UserId>('usr')
export const newOrderId = () => createId<OrderId>('ord')

Use it everywhere

src/services/user.ts
import type { UserId } from '@/types/ids'

// Functions that need a UserId now say so explicitly
export async function getUser(id: UserId) {
  return db.users.findOne({ id })
}

export async function deleteUser(id: UserId) {
  await db.users.delete({ id })
}

Watch TypeScript catch mistakes

import { newUserId, newOrderId } from '@/types/ids'
import { getUser } from '@/services/user'

const userId  = newUserId()   // type: UserId
const orderId = newOrderId()  // type: OrderId

await getUser(userId)   // ✓ fine
await getUser(orderId)  // ✗ Error: Argument of type 'OrderId' is not
                        //   assignable to parameter of type 'UserId'

What the IDs look like at runtime

safeids generates human-readable prefixed IDs using crypto.randomUUID() or crypto.getRandomValues. The prefix is optional but highly recommended — it makes IDs instantly recognisable in logs, databases, and error messages.

import { createId } from 'safeids'
import type { UserId, OrderId } from '@/types/ids'

const userId  = createId<UserId>('usr')   // → "usr_k2p9xm"
const orderId = createId<OrderId>('ord')  // → "ord_f7qrn1"

// Without a prefix (still typed, just no prefix)
const anon = createId<UserId>()           // → "a8mn2q"

Next steps