Unique ID
Introduction
Section titled “Introduction”Entities need identifiers that remain stable while their other data changes. A plain string carries no indication of which kind of entity it identifies, so code can accidentally mix identifiers for different domain concepts.
UniqueId<TKind> wraps a UUID value and uses TKind as a compile-time marker. Create identifiers through its static factory; the class has a private constructor and freezes each instance.
Create an Identifier
Section titled “Create an Identifier”Call UniqueId.create() with a kind name. The factory generates a UUID v4 when no usable identifier is provided:
import { UniqueId } from '@xeno-js/shared'
const orderId = UniqueId.create('Order')
console.log(orderId.toString())The generated value is available as a string through toString(), or as the underlying Guid through getValue().
Use Typed Identifiers
Section titled “Use Typed Identifiers”Use a different kind for each domain identifier. TypeScript then prevents passing one kind where another is expected:
import { UniqueId } from '@xeno-js/shared'
type OrderId = UniqueId<'Order'>type CustomerId = UniqueId<'Customer'>
function loadOrder(id: OrderId): void { console.log(`Loading order ${id.toString()}`)}
const orderId: OrderId = UniqueId.create('Order')const customerId: CustomerId = UniqueId.create('Customer')
loadOrder(orderId)// loadOrder(customerId) // Type error: a Customer ID is not an Order ID.The kind argument exists for typing; it does not change the UUID or add a runtime prefix. Keep the kind string consistent wherever the same identifier type is used.
Supply an Existing Identifier
Section titled “Supply an Existing Identifier”Pass an existing UUID string as the optional second argument when rebuilding an identifier, for example when mapping a value read from storage:
import { UniqueId } from '@xeno-js/shared'
const storedOrderId = 'c0a80123-4567-489a-8abc-1234567890ab'const orderId = UniqueId.create('Order', storedOrderId)
console.log(orderId.toString())UniqueId.create() keeps the supplied string only when it is non-empty and a valid GUID. If it is empty or invalid, the factory generates a new UUID instead. Validate external input separately if silently replacing an invalid value is not appropriate for the calling workflow.
Compare Identifiers
Section titled “Compare Identifiers”Use equals() to compare identifiers of the same kind:
import { UniqueId } from '@xeno-js/shared'
const originalId = UniqueId.create('Order', 'c0a80123-4567-489a-8abc-1234567890ab')const rehydratedId = UniqueId.create('Order', 'c0a80123-4567-489a-8abc-1234567890ab')const anotherOrderId = UniqueId.create('Order')
console.log(originalId.equals(rehydratedId)) // trueconsole.log(originalId.equals(anotherOrderId)) // falseEquality compares the underlying GUID values. equals() also returns false when the other value is not a UniqueId instance.
Behavior
Section titled “Behavior”create(kind)generates a UUID v4.create(kind, id)usesidonly when it is non-empty and a valid GUID; otherwise, it generates a UUID v4.toString()returns the identifier’s string representation, andgetValue()returns its underlyingGuid.equals()compares the underlying values.- Instances are frozen after construction.
- The generic kind distinguishes identifier types at compile time; it does not alter their runtime representation.
Support Us
Section titled “Support Us”Xeno.JS is an MIT-licensed open source project. It can grow thanks to the support of these awesome people. If you’d like to join them, please read more at support section
