safeids
A tiny TypeScript library that turns your plain string IDs into distinct branded types — so passing a userId where an orderId belongs is a compile error, not a production bug.
The problem
TypeScript treats all string IDs as interchangeable. This compiles without error:
function getOrder(userId: string, orderId: string) {
return db.orders.findOne({ id: userId }) // oops — wrong ID, no error
}
getOrder(order.id, user.id) // args swapped — still compiles ✓The bug ships. It fails silently at runtime.
The solution
safeids gives each ID type a unique brand. TypeScript now treats UserId and OrderId as incompatible — even though both are strings at runtime.
import { brand, createId } from 'safeids'
type UserId = brand<string, 'UserId'>
type OrderId = brand<string, 'OrderId'>
function getOrder(userId: UserId, orderId: OrderId) {
return db.orders.findOne({ id: orderId }) // forced to use the right ID
}
const userId = createId<UserId>('usr')
const orderId = createId<OrderId>('ord')
getOrder(orderId, userId)
// ^^^^^^^ Error: Argument of type 'OrderId' is not assignable to 'UserId'Quick start
Installation →
Install safeids and create your first branded ID in under two minutes.
Concepts →
Understand how phantom types work and why string isn't always string.
API Reference →
Full reference for createId, fromString, isId, brand, and Brand.
Zod Integration →
Validate branded IDs at runtime using zodBrand and Zod schemas.