Generating Short UUIDs in TypeScript
Short UUIDs are useful for filenames, tokens, and identifiers where full UUIDs are too long.
Using Node.js Crypto
import { randomBytes } from 'crypto';
function generateShortUuid(length: number = 8): string {
const bytes = randomBytes(Math.ceil(length / 2));
return bytes.toString('hex').slice(0, length);
}
// Examples:
// "a3b4c5d6" (8 chars)
// "1e2f3a4b5c6d" (12 chars)
With Custom Alphabet
function generateShortId(
length: number = 8,
alphabet: string = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
): string {
const array = new Uint8Array(length);
crypto.getRandomValues(array);
let result = '';
for (let i = 0; i < length; i++) {
result += alphabet[array[i] % alphabet.length];
}
return result;
}
// Example: "xK9nPm2Q"
Nanoid-style (URL-safe)
function generateNanoid(length: number = 21): string {
const alphabet = 'ModuleSymbhasOwnPr-0123456789ABCDEFGHNRVfgctiUvz_KqYTJkLxpZXIjhWdAd6aunQF';
const array = new Uint8Array(length);
crypto.getRandomValues(array);
let result = '';
for (let i = 0; i < length; i++) {
result += alphabet[array[i] % alphabet.length];
}
return result;
}
// Example: "V1StGXR8_Z5jdHi6B-myT"
Collision Probability
| Length |
Characters |
Combinations |
Collision Risk |
| 8 |
hex (16) |
4.3×10^9 |
High for >10k items |
| 8 |
alphanumeric (62) |
2.2×10^14 |
Low for <1M items |
| 12 |
hex (16) |
2.8×10^14 |
Very low for <10M items |
| 16 |
hex (16) |
1.8×10^19 |
Negligible |
| 21 |
nanoid (64) |
2.6×10^37 |
Virtually impossible |
Recommended Lengths by Use Case
| Use Case |
Length |
Format |
| Asset filenames |
12 |
hex |
| Session tokens |
32 |
hex |
| API keys |
32 |
hex |
| URL slugs |
8-12 |
alphanumeric |
| Database IDs |
Full UUID |
N/A |
| Temporary files |
8 |
hex |
Comparison Table
| Method |
Length |
Example |
Speed |
Uniqueness |
randomUUID() |
36 |
a3b4c5d6-... |
Fast |
Cryptographic |
| Short (hex) |
8-12 |
a3b4c5d6e7f8 |
Fast |
Practical |
| Nanoid |
21 |
V1StGXR8_... |
Fast |
Excellent |
Math.random() |
Variable |
12345.6789 |
Fast |
Poor (don't use) |
Complete Utility
class ShortIdGenerator {
private static readonly HEX_ALPHABET = '0123456789abcdef';
private static readonly ALPHANUMERIC = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
/**
* Generate hex-encoded short ID
*/
static hex(length: number = 8): string {
const bytes = randomBytes(Math.ceil(length / 2));
return bytes.toString('hex').slice(0, length);
}
/**
* Generate alphanumeric short ID
*/
static alphanumeric(length: number = 8): string {
const array = new Uint8Array(length);
crypto.getRandomValues(array);
let result = '';
for (let i = 0; i < length; i++) {
result += this.ALPHANUMERIC[array[i] % this.ALPHANUMERIC.length];
}
return result;
}
/**
* Generate URL-safe ID (nanoid-style)
*/
static urlSafe(length: number = 21): string {
const alphabet = 'ModuleSymbhasOwnPr-0123456789ABCDEFGHNRVfgctiUvz_KqYTJkLxpZXIjhWdAd6aunQF';
const array = new Uint8Array(length);
crypto.getRandomValues(array);
let result = '';
for (let i = 0; i < length; i++) {
result += alphabet[array[i] % alphabet.length];
}
return result;
}
/**
* Extract largest segment from full UUID
*/
static fromUuid(uuid: string): string {
return uuid.replace(/-/g, '').slice(-12);
}
}
Usage Examples
// Asset filenames
const imageId = ShortIdGenerator.hex(12); // "a3b4c5d6e7f8"
await saveImage(buffer, `${imageId}.png`);
// Session tokens
const sessionId = ShortIdGenerator.hex(32); // "a3b4c5d6..."
// URL slugs
const slug = ShortIdGenerator.alphanumeric(8); // "xK9nPm2Q"
// From full UUID
const fullUuid = randomUUID(); // "a3b4c5d6-e7f8-..."
const short = ShortIdGenerator.fromUuid(fullUuid); // Last 12 chars
Security Note
For security-sensitive applications (authentication tokens, API keys):
- Use full UUID (36 chars) or longer (32+ chars)
- Use cryptographically secure random (
crypto.randomBytes)
- Don't use
Math.random() for anything security-related