Type Formats come with a comprehensive set of built-in formats for common validation scenarios. This page documents all available formats, their parameters, and the differences between similar formats.
Import from @mionjs/type-formats/StringFormats:
import {FormatEmail, FormatEmailStrict, FormatEmailPunycode} from '@mionjs/type-formats/StringFormats';
FormatEmail vs FormatEmailStrict| Format | Validation | Performance | Use Case |
|---|---|---|---|
FormatEmail | Pattern-based (regex) | Faster | General email validation, allows special chars like +, () |
FormatEmailStrict | Component-based | Slower | Strict RFC compliance, validates local part and domain separately |
| Format | PostgreSQL | MySQL | SQLite |
|---|---|---|---|
FormatEmail | varchar(254) | varchar(254) | text() |
FormatEmail uses a single regex pattern for validation. It allows special characters in the local part:
import {FormatEmail} from '@mionjs/type-formats/StringFormats';
type UserEmail = FormatEmail;
// Valid
('user@example.com'); // ✓
('user+tag@example.com'); // ✓ (allows + for email aliases)
('user(comment)@test.com'); // ✓
// Invalid
('user@name@example.com'); // ✗ (multiple @)
('@example.com'); // ✗ (missing local part)
FormatEmail is the most performant option for email validation. It uses a single regex pattern which makes it significantly faster than component-based validation.FormatEmailStrict validates each component separately (local part, domain, TLD):
import {FormatEmailStrict} from '@mionjs/type-formats/StringFormats';
// Valid
('user@example.com'); // ✓
('user.name@sub.domain.com'); // ✓
// Invalid (stricter than FormatEmail)
('user+tag@example.com'); // ✗ (disallows special chars)
('user(comment)@test.com'); // ✗ (disallows parentheses)
FormatEmailPunycode allows internationalized domains (punycode):
import {FormatEmailPunycode} from '@mionjs/type-formats/StringFormats';
type InternationalEmail = FormatEmailPunycode;
// Valid
('user@xn--80akhbyknj4f.xn--p1ai'); // ✓ (punycode domain)
('user@sub-domain.example.com'); // ✓ (hyphenated domains)
Import from @mionjs/type-formats/StringFormats:
import {FormatUrl, FormatUrlHttp, FormatUrlFile} from '@mionjs/type-formats/StringFormats';
FormatUrl vs FormatUrlHttp| Format | Allowed Protocols | Use Case |
|---|---|---|
FormatUrl | http, https, ftp, ftps, ws, wss | General URL validation |
FormatUrlHttp | http, https only | Web URLs only |
FormatUrlFile | file only | Local file paths |
| Format | PostgreSQL | MySQL | SQLite |
|---|---|---|---|
FormatUrl | varchar(2048) | varchar(2048) | text() |
import {FormatUrl, FormatUrlHttp, FormatUrlFile} from '@mionjs/type-formats/StringFormats';
type GeneralUrl = FormatUrl;
type WebUrl = FormatUrlHttp;
type FileUrl = FormatUrlFile;
// FormatUrl - accepts multiple protocols
('http://example.com'); // ✓
('https://example.com'); // ✓
('ftp://example.com'); // ✓
('ws://example.com'); // ✓
// FormatUrlHttp - HTTP/HTTPS only
('http://example.com'); // ✓
('https://example.com'); // ✓
('ftp://example.com'); // ✗
('ws://example.com'); // ✗
// FormatUrlFile - file protocol only
('file://hello.png'); // ✓
('file:///c:/lorem/ipsum.jpg'); // ✓
('http://example.com'); // ✗
Import from @mionjs/type-formats/StringFormats:
import {FormatDomain, FormatDomainStrict} from '@mionjs/type-formats/StringFormats';
FormatDomain vs FormatDomainStrict| Format | Validation | Performance | Error Messages |
|---|---|---|---|
FormatDomain | Pattern-based (regex) | Faster | Generic errors |
FormatDomainStrict | Component-based | Slower | Detailed errors per component |
| Format | PostgreSQL | MySQL | SQLite |
|---|---|---|---|
FormatDomain | varchar(253) | varchar(253) | text() |
import {FormatDomain, FormatDomainStrict} from '@mionjs/type-formats/StringFormats';
type QuickDomain = FormatDomain;
type DetailedDomain = FormatDomainStrict;
// Both validate the same cases
('example.com'); // ✓
('sub.example.com'); // ✓
('example.co.uk'); // ✓
// Invalid for both
('example'); // ✗ (missing TLD)
('example..com'); // ✗ (empty part)
('exa!mple.com'); // ✗ (invalid characters)
Custom Domain Parameters:
import {FormatDomainStrict} from '@mionjs/type-formats/StringFormats';
type SocialMediaDomain = FormatDomainStrict<{
maxLength: 200;
minParts: 2;
maxParts: 3;
names: {
allowedValues: {
val: ['facebook', 'twitter', 'instagram', 'linkedin'];
errorMessage: 'Only social media domains allowed';
};
};
tld: {
allowedValues: {
val: ['com'];
errorMessage: 'Only .com TLD allowed';
};
};
}>;
import {FormatUUIDv4, FormatUUIDv7} from '@mionjs/type-formats/StringFormats';
type UserId = FormatUUIDv4; // Standard UUID v4: xxxxxxxx-xxxx-4xxx-xxxx-xxxxxxxxxxxx
type EventId = FormatUUIDv7; // Time-ordered UUID v7: xxxxxxxx-xxxx-7xxx-xxxx-xxxxxxxxxxxx
| Format | PostgreSQL | MySQL | SQLite |
|---|---|---|---|
FormatUUID / FormatUUIDv7 | uuid() | varchar(36) | text() |
import {FormatIP, FormatIPv4, FormatIPv6, FormatIPWithPort} from '@mionjs/type-formats/StringFormats';
type AnyIP = FormatIP; // IPv4 or IPv6
type OnlyV4 = FormatIPv4; // IPv4 only
type OnlyV6 = FormatIPv6; // IPv6 only
type WithPort = FormatIPWithPort; // Any IP with port support
// Examples
('192.168.0.1'); // ✓ FormatIPv4
('2001:0db8:85a3::8a2e:0370:7334'); // ✓ FormatIPv6
('localhost'); // ✓ (when allowLocalHost: true)
IP Format Parameters:
| Parameter | Type | Description |
|---|---|---|
version | 4 | 6 | 'any' | IP version to validate |
allowLocalHost | boolean | Allow localhost values (127.0.0.1, ::1) |
allowPort | boolean | Allow port suffix (:8080) |
| Format | PostgreSQL | MySQL | SQLite |
|---|---|---|---|
FormatIP / FormatIPv4 / FormatIPv6 | inet() | varchar(45) | text() |
Available Date Formats:
| Format | Example | Description |
|---|---|---|
'ISO' or 'YYYY-MM-DD' | 2023-01-15 | ISO 8601 date (default) |
'DD-MM-YYYY' | 15-01-2023 | European format |
'MM-DD-YYYY' | 01-15-2023 | US format |
'YYYY-MM' | 2023-01 | Year and month only |
'MM-DD' | 01-15 | Month and day only |
'DD-MM' | 15-01 | Day and month only |
import {FormatStringDate} from '@mionjs/type-formats/StringFormats';
// Default ISO format
type ISODate = FormatStringDate; // 'YYYY-MM-DD'
// Custom formats
type EuropeanDate = FormatStringDate<{format: 'DD-MM-YYYY'}>;
type USDate = FormatStringDate<{format: 'MM-DD-YYYY'}>;
type MonthYear = FormatStringDate<{format: 'YYYY-MM'}>;
// Validates leap years correctly
('2000-02-29'); // ✓ (leap year)
('1900-02-29'); // ✗ (not a leap year)
| Format | PostgreSQL | MySQL | SQLite |
|---|---|---|---|
FormatStringDate | date() | date() | text() |
Available Time Formats:
| Format | Example | Description |
|---|---|---|
'ISO' or 'HH:mm:ss[.mmm]TZ' | 14:30:00Z | ISO 8601 with timezone (default) |
'HH:mm:ss[.mmm]' | 14:30:00.123 | With optional milliseconds |
'HH:mm:ss' | 14:30:00 | Hours, minutes, seconds |
'HH:mm' | 14:30 | Hours and minutes |
'mm:ss' | 30:45 | Minutes and seconds |
'HH' | 14 | Hours only |
'mm' | 30 | Minutes only |
'ss' | 45 | Seconds only |
import {FormatStringTime} from '@mionjs/type-formats/StringFormats';
// Default ISO format with timezone
type ISOTime = FormatStringTime; // 'HH:mm:ss[.mmm]TZ'
// Custom formats
type SimpleTime = FormatStringTime<{format: 'HH:mm:ss'}>;
type ShortTime = FormatStringTime<{format: 'HH:mm'}>;
type Duration = FormatStringTime<{format: 'mm:ss'}>;
// ISO time examples
('14:30:00Z'); // ✓ UTC
('14:30:00+05:30'); // ✓ with offset
('14:30:00.123Z'); // ✓ with milliseconds
| Format | PostgreSQL | MySQL | SQLite |
|---|---|---|---|
FormatStringTime | time() | time() | text() |
DateTime combines date and time formats with a configurable separator:
import {FormatStringDateTime} from '@mionjs/type-formats/StringFormats';
// Default: ISO date + ISO time, separated by 'T'
type ISODateTime = FormatStringDateTime;
// Example: '2023-01-15T14:30:00Z'
// Custom combination
type CustomDateTime = FormatStringDateTime<{
date: {format: 'DD-MM-YYYY'};
time: {format: 'HH:mm'};
splitChar: ' '; // space separator instead of 'T'
}>;
// Example: '15-01-2023 14:30'
// Short datetime
type ShortDateTime = FormatStringDateTime<{
date: {format: 'MM-DD'};
time: {format: 'HH'};
}>;
// Example: '01-15T14'
DateTime Parameters:
| Parameter | Type | Description |
|---|---|---|
date | FormatParams_Date | Date format configuration |
time | FormatParams_Time | Time format configuration |
splitChar | string | Separator between date and time (default: 'T') |
| Format | PostgreSQL | MySQL | SQLite |
|---|---|---|---|
FormatStringDateTime | timestamp() | datetime() | text() |
import {
FormatAlphaNumeric,
FormatAlpha,
FormatNumeric,
FormatLowercase,
FormatUppercase,
} from '@mionjs/type-formats/StringFormats';
type Username = FormatAlphaNumeric; // Letters and numbers only
type Name = FormatAlpha; // Letters only (supports Unicode)
type Code = FormatNumeric; // Digits only
type Slug = FormatLowercase; // Forced lowercase
type Initials = FormatUppercase; // Forced uppercase
Use FormatString to define custom string constraints with validators and transformers:
import {FormatString} from '@mionjs/type-formats/StringFormats';
// Username: 3-20 chars, lowercase, trimmed
type Username = FormatString<{
minLength: 3;
maxLength: 20;
lowercase: true;
trim: true;
}>;
// Slug with pattern validation
const slugRegex = /^[a-z0-9-]+$/;
type Slug = FormatString<{
minLength: 1;
maxLength: 100;
pattern: {
val: typeof slugRegex;
errorMessage: 'Slug can only contain lowercase letters, numbers, and hyphens';
mockSamples: ['my-post', 'hello-world', 'article-123'];
};
}>;
// Name with allowed characters only
type SafeName = FormatString<{
minLength: 1;
maxLength: 50;
allowedChars: {
val: 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ';
errorMessage: 'Name can only contain letters and spaces';
};
capitalize: true;
}>;
String Format Parameters:
| Parameter | Type | Description |
|---|---|---|
| Validators | ||
minLength | number | Minimum string length |
maxLength | number | Maximum string length |
length | number | Exact string length |
pattern | {val: RegExp; errorMessage: string; mockSamples: string[]} | Regex pattern validation |
allowedChars | {val: string; errorMessage: string} | Only these characters allowed |
disallowedChars | {val: string; errorMessage: string; mockSamples: string} | These characters not allowed |
allowedValues | {val: string[]; errorMessage: string} | Only these exact values allowed |
disallowedValues | {val: string[]; errorMessage: string} | These exact values not allowed |
| Transformers | ||
lowercase | boolean | Convert to lowercase |
uppercase | boolean | Convert to uppercase |
capitalize | boolean | Capitalize first letter |
trim | boolean | Remove leading/trailing whitespace |
replace | {searchValue: string; replaceValue: string} | Replace first occurrence |
replaceAll | {searchValue: string; replaceValue: string} | Replace all occurrences |
pattern, disallowedChars, or disallowedValues, you must provide mockSamples so the mock generator knows what valid values to produce.Import from @mionjs/type-formats/NumberFormats:
import {
FormatNumber,
FormatInteger,
FormatFloat,
FormatPositive,
FormatNegative,
FormatPositiveInt,
FormatNegativeInt,
FormatInt8,
FormatInt16,
FormatInt32,
FormatUInt8,
FormatUInt16,
FormatUInt32,
} from '@mionjs/type-formats/NumberFormats';
| Type | Description | Range | Binary Size |
|---|---|---|---|
FormatInteger | Any integer | Number.MIN_SAFE_INTEGER to Number.MAX_SAFE_INTEGER | 8 bytes |
FormatFloat | Must be a float | Number.MIN_VALUE to Number.MAX_VALUE | 8 bytes |
FormatPositive | ≥ 0 | 0 to Number.MAX_VALUE | 8 bytes |
FormatNegative | ≤ 0 | Number.MIN_VALUE to 0 | 8 bytes |
FormatPositiveInt | Positive integer | 0 to Number.MAX_SAFE_INTEGER | 8 bytes |
FormatNegativeInt | Negative integer | Number.MIN_SAFE_INTEGER to 0 | 8 bytes |
FormatInt8 | 8-bit signed | -2⁷ to 2⁷-1 (-128 to 127) | 1 byte |
FormatInt16 | 16-bit signed | -2¹⁵ to 2¹⁵-1 (-32,768 to 32,767) | 2 bytes |
FormatInt32 | 32-bit signed | -2³¹ to 2³¹-1 (-2,147,483,648 to 2,147,483,647) | 4 bytes |
FormatUInt8 | 8-bit unsigned | 0 to 2⁸-1 (255) | 1 byte |
FormatUInt16 | 16-bit unsigned | 0 to 2¹⁶-1 (65,535) | 2 bytes |
FormatUInt32 | 32-bit unsigned | 0 to 2³²-1 (4,294,967,295) | 4 bytes |
FormatInt8, FormatUInt16) are encoded more efficiently than generic numbers, resulting in smaller binary payloads.| Format | PostgreSQL | MySQL | SQLite |
|---|---|---|---|
FormatInteger / FormatPositiveInt / FormatNegativeInt | integer() | int() | integer() |
FormatInt8 / FormatInt16 / FormatInt32 | integer() | int() | integer() |
FormatUInt8 / FormatUInt16 / FormatUInt32 | integer() | int() | integer() |
FormatFloat / FormatPositive / FormatNegative | doublePrecision() | double() | real() |
import {FormatNumber} from '@mionjs/type-formats/NumberFormats';
// Age with valid range
type Age = FormatNumber<{
min: 0;
max: 120;
integer: true;
}>;
// Percentage with decimals
type Percentage = FormatNumber<{
min: 0;
max: 100;
}>;
// Price must be multiple of 0.01 (cents)
type Price = FormatNumber<{
min: 0;
multipleOf: 1; // multipleOf must be integer
integer: true; // store as cents
}>;
Number Format Parameters:
| Parameter | Type | Description |
|---|---|---|
min | number | Minimum value (inclusive) |
max | number | Maximum value (inclusive) |
gt | number | Greater than (exclusive) |
lt | number | Less than (exclusive) |
integer | boolean | Must be an integer |
float | boolean | Must be a float |
multipleOf | number | Must be a multiple of (integer only) |
Note: min/max and gt/lt are mutually exclusive. integer and float are also mutually exclusive.
Import from @mionjs/type-formats/BigintFormats:
import {
FormatBigInt,
FormatBigPositive,
FormatBigNegative,
FormatBigPositiveInt,
FormatBigNegativeInt,
FormatBigInt64,
FormatBigUInt64,
} from '@mionjs/type-formats/BigintFormats';
// Predefined bigint formats
type AccountBalance = FormatBigPositive; // bigint >= 0n
type DebtAmount = FormatBigNegative; // bigint <= 0n
type ItemCount = FormatBigPositiveInt; // positive integer bigint
type Adjustment = FormatBigNegativeInt; // negative integer bigint
type DbBigInt = FormatBigInt64; // signed 64-bit, 8-byte binary
type DbUBigInt = FormatBigUInt64; // unsigned 64-bit, 8-byte binary
// Custom bigint format with all parameters
type Score = FormatBigInt<{
min: 0n;
max: 1000000n;
multipleOf: 10n;
}>;
type Wallet = {
balance: AccountBalance;
debt: DebtAmount;
items: ItemCount;
adjustment: Adjustment;
dbId: DbBigInt;
dbUid: DbUBigInt;
score: Score;
};
| Type | Description | Range | Binary Size |
|---|---|---|---|
FormatBigInt | Generic bigint with configurable parameters | Unbounded (configurable) | Variable (string fallback for values outside Int64/UInt64) |
FormatBigPositive | Non-negative bigint | 0n to ∞ | Variable |
FormatBigNegative | Non-positive bigint | -∞ to 0n | Variable |
FormatBigPositiveInt | Non-negative integer bigint | 0n to ∞ | Variable |
FormatBigNegativeInt | Non-positive integer bigint | -∞ to 0n | Variable |
FormatBigInt64 | Signed 64-bit bigint | -9223372036854775808n to 9223372036854775807n | 8 bytes |
FormatBigUInt64 | Unsigned 64-bit bigint | 0n to 18446744073709551615n | 8 bytes |
FormatBigInt64 and FormatBigUInt64 are encoded as fixed 8-byte binary values using DataView.setBigInt64/setBigUInt64. Other bigint formats fall back to string serialization for values that don't fit in the Int64/UInt64 range, so prefer the typed variants when your values are bounded — they produce smaller and faster binary payloads.| Format | PostgreSQL | MySQL | SQLite |
|---|---|---|---|
FormatBigInt / FormatBigPositive / FormatBigNegative | bigint({mode: 'bigint'}) | bigint({mode: 'bigint'}) | blob({mode: 'bigint'}) |
FormatBigPositiveInt / FormatBigNegativeInt | bigint({mode: 'bigint'}) | bigint({mode: 'bigint'}) | blob({mode: 'bigint'}) |
FormatBigInt64 / FormatBigUInt64 | bigint({mode: 'bigint'}) | bigint({mode: 'bigint'}) | blob({mode: 'bigint'}) |
Use FormatBigInt to define custom bigint constraints. The custom example in the import above shows min, max, and multipleOf combined.
BigInt Format Parameters:
| Parameter | Type | Description |
|---|---|---|
min | bigint | Minimum value (inclusive) |
max | bigint | Maximum value (inclusive) |
gt | bigint | Greater than (exclusive) |
lt | bigint | Less than (exclusive) |
multipleOf | bigint | Must be a multiple of this value (must be > 0n) |
Note: min/gt and max/lt are mutually exclusive — use one or the other in each pair.