Branded TypeScript IDs that make userId where orderId belongs a compile error — not a production incident.
Before
function processOrder(userId: string, orderId: string) {
await db.orders.findOne({ id: userId }) // silent bug ❌
}
processOrder(order.id, user.id) // compiles fine
After safeids
function processOrder(userId: UserId, orderId: OrderId) {
await db.orders.findOne({ id: orderId }) // safe ✓
}
processOrder(order.id, user.id)
// Type Error: OrderId ≠ UserId — caught at compile time ✓
Why safeids
Brands are erased at compile time. No overhead to your bundle.
Pass the wrong ID type anywhere and TypeScript catches it instantly.
Optional Zod schemas for runtime validation at API boundaries.
Human-readable prefixes like usr_, ord_, prd_ for instant ID recognition.
Thoroughly tested edge cases, including Zod and string validation.
Ships both ESM and CommonJS builds with TypeScript declarations.
Interactive
Define entities, generate typed code, and watch type errors appear in real time.
Define Domain
Generated Code
import { brand, createId } from 'safeids'
// Branded types — ID domain mixups are now compile errors
type userId = brand<string, 'userId'>
type orderId = brand<string, 'orderId'>
type productId = brand<string, 'productId'>
// ID generators — typed and prefixed
const ser_id = createId<userId>('usr')
const rder_id = createId<orderId>('ord')
const roduct_id = createId<productId>('prd')Live Playground
Define Domain
Generated Code
import { brand, createId } from 'safeids'
// Branded types — ID domain mixups are now compile errors
type userId = brand<string, 'userId'>
type orderId = brand<string, 'orderId'>
type productId = brand<string, 'productId'>
// ID generators — typed and prefixed
const ser_id = createId<userId>('usr')
const rder_id = createId<orderId>('ord')
const roduct_id = createId<productId>('prd')Live Playground
Process
One command. No peer deps.
Create branded types for each ID entity.
Use the builder or write types manually.
Wrong IDs are compile errors from now on.
Documentation
Comprehensive guides from first install to production-ready patterns.
Install safeids and create your first branded ID in under two minutes. Works with Next.js, Remix, tRPC, Prisma — any TypeScript project.
Read more →Understand phantom types and why Brand<string, "UserId"> is incompatible with Brand<string, "OrderId"> even though both are strings at runtime.
Read more →Full reference for createId, fromString, isId, brand, and Brand — with parameter tables, return types, and throws documentation.
Read more →Validate branded IDs at runtime using zodBrand. Perfect for API route handlers, tRPC procedures, and form validation.
Read more →7 copy-paste patterns: Prisma queries, Next.js API routes, React props, tRPC procedures, and a step-by-step migration guide.
Read more →Start here for an overview of what safeids solves, when to use it, and how to navigate the rest of the docs.
Read more →Get started
Drop safeids into any TypeScript project. No config, no schema files, no runtime cost.
$ npm install safeids
$ pnpm add safeids
$ yarn add safeids