RunTypes

Supported Types

Comprehensive list of supported TypeScript types and feature comparison with other validation libraries.

@mionkit/run-types supports a comprehensive set of TypeScript types.
The long term goal is to fully support all typescript features for full compatibility.

Type Support Comparison

Type CategoryTyperun-typesZodTypiaAJVTypeBox
Primitivesstring
number
boolean
bigint
symbol
null
undefined
void
never
any
unknown
LiteralsString literals
Number literals
Boolean literals
Template literals
Objectsinterface
type aliases
class
Nested objects
Optional properties
Readonly properties
Index signatures
CollectionsArray<T>
Tuple
Record<K, V>
Native ObjectsDate
RegExp
Map<K, V>
Set<T>
EnumsNumeric enums
String enums
Const enums
Unions & IntersectionsUnion types
Discriminated unions🚀
Intersection types
Utility TypesPartial<T>
Required<T>
Pick<T, K>
Omit<T, K>
Exclude<T, U>
Extract<T, U>
NonNullable<T>
Awaited<T>
Parameters<F>
ReturnType<F>
String UtilitiesUppercase<S>⚠️
Lowercase<S>⚠️
Capitalize<S>⚠️
Uncapitalize<S>
FunctionsFunction types💎
Method signatures
Call signatures
Rest parameters
AdvancedCircular references⚠️
Generic types
Conditional types⚠️⚠️
Mapped types
Type inferencex
⚠️ = Partial support with limitations
🚀 = mion has optimized type checking for discriminated unions.
💎 = mion is the only framework from the table that can extract types directly from functions
import {reflectFunction} from '@mionkit/run-types';

function sayHello(name: string): string {
    return `Hello ${name}`;
}

const fnType = reflectFunction(sayHello);
// fnType = FunctionRunType<type (name: string) => string>

Feature Comparison

Featurerun-typesZodTypiaAJVTypeBox
Core
Type inference from TS
Schema-first approach
JIT compilationAOT
TSC build required
Validation
Type validation
Strict validation
Error messages
Custom error messages
Serialization
JSON serialization
Binary serializationPROTOBUF
Date handling
BigInt handling
Map/Set handling
Other
Mock data generation
Function reflection
AOT code generation

Approach Comparison

Schema-First (Zod, AJV)

With schema-first libraries, you define schemas separately from your TypeScript types:

import {z} from 'zod';

// Zod example - schema is source of truth
const UserSchema = z.object({
    name: z.string(),
    age: z.number(),
    email: z.string().email(),
});
type User = z.infer<typeof UserSchema>;

Pros: No build step, works everywhere Cons: Duplicate definitions, schemas can drift from actual types

Type-First (run-types, Typia)

With type-first libraries, TypeScript types are the source of truth:

import {createIsTypeFn} from '@mionkit/run-types';
import {StrEmail} from '@mionkit/type-formats/FormatsString';

// run-types example - TypeScript is source of truth
interface User {
    name: string;
    age: number;
    email: StrEmail; // Using type formats for validation
}

async function example() {
    const validate = await createIsTypeFn<User>();
}

Pros: Single source of truth, no schema duplication Cons: Requires TypeScript compiler integration

run-types vs Typia: Function Reflection

The key difference between run-types and Typia is function reflection. While both are type-first, Typia cannot extract types directly from function signatures, requiring you to declare types separately and pass them as generic parameters.

Typia + Hono example: (required to create validators manually)

import {Hono} from 'hono';
import {typiaValidator} from '@hono/typia-validator';
import typia from 'typia';

interface IBbsArticle {
    // ❌ Must declare type separately
    id: string;
    title: string;
    body: string;
    created_at: string;
}

// ❌ Must create validator with explicit generic type
const validate = typia.createValidate<IBbsArticle>();

const app = new Hono();

app.post(
    '/',
    typiaValidator('json', validate), // ❌ Pass validator as middleware
    (c) => {
        const data = c.req.valid('json');
        return c.json({id: data.id, title: data.title, body: data.body});
    }
);

mion example (types extracted from functions and validated automatically):

import {Routes, route} from '@mionkit/router';

interface Article {
    id: string;
    title: string;
    body: string;
}

type NewArticle = Omit<Article, 'id'>;

declare function generateId(): string;

// ✅ Types are extracted directly from the function signature
const routes = {
    createArticle: route((ctx, article: NewArticle): Article => {
        return {id: generateId(), ...article};
    }),
} satisfies Routes;

With mion, the router automatically extracts parameter and return types from your route handlers — no separate type declarations, no generic parameters, no middleware wiring, and no risk of types drifting out of sync.


When to Use run-types

Use run-types when:

  • You want TypeScript types as the single source of truth
  • You need JSON serialization with complex types (Date, Map, Set, BigInt)
  • You need binary serialization for performance
  • You want mock data generation from types
  • You're building APIs with mion

Consider alternatives when:

  • You need to share schemas with non-TypeScript consumers
  • You're building a library consumed by vanilla JavaScript
  • You need schemas defined at runtime

at runtime