@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 Category | Type | run-types | Zod | Typia | AJV | TypeBox |
|---|---|---|---|---|---|---|
| Primitives | string | ✅ | ✅ | ✅ | ✅ | ✅ |
number | ✅ | ✅ | ✅ | ✅ | ✅ | |
boolean | ✅ | ✅ | ✅ | ✅ | ✅ | |
bigint | ✅ | ✅ | ✅ | ❌ | ✅ | |
symbol | ✅ | ✅ | ✅ | ❌ | ✅ | |
null | ✅ | ✅ | ✅ | ✅ | ✅ | |
undefined | ✅ | ✅ | ✅ | ❌ | ✅ | |
void | ✅ | ✅ | ✅ | ❌ | ✅ | |
never | ✅ | ✅ | ✅ | ❌ | ✅ | |
any | ✅ | ✅ | ✅ | ✅ | ✅ | |
unknown | ✅ | ✅ | ✅ | ✅ | ✅ | |
| Literals | String literals | ✅ | ✅ | ✅ | ✅ | ✅ |
| Number literals | ✅ | ✅ | ✅ | ✅ | ✅ | |
| Boolean literals | ✅ | ✅ | ✅ | ✅ | ✅ | |
| Template literals | ❌ | ❌ | ✅ | ❌ | ✅ | |
| Objects | interface | ✅ | ✅ | ✅ | ✅ | ✅ |
type aliases | ✅ | ✅ | ✅ | ✅ | ✅ | |
class | ✅ | ❌ | ✅ | ❌ | ❌ | |
| Nested objects | ✅ | ✅ | ✅ | ✅ | ✅ | |
| Optional properties | ✅ | ✅ | ✅ | ✅ | ✅ | |
| Readonly properties | ✅ | ✅ | ✅ | ❌ | ✅ | |
| Index signatures | ✅ | ✅ | ✅ | ✅ | ✅ | |
| Collections | Array<T> | ✅ | ✅ | ✅ | ✅ | ✅ |
Tuple | ✅ | ✅ | ✅ | ✅ | ✅ | |
Record<K, V> | ✅ | ✅ | ✅ | ✅ | ✅ | |
| Native Objects | Date | ✅ | ✅ | ✅ | ❌ | ✅ |
RegExp | ✅ | ❌ | ✅ | ❌ | ❌ | |
Map<K, V> | ✅ | ✅ | ✅ | ❌ | ❌ | |
Set<T> | ✅ | ✅ | ✅ | ❌ | ❌ | |
| Enums | Numeric enums | ✅ | ✅ | ✅ | ❌ | ❌ |
| String enums | ✅ | ✅ | ✅ | ❌ | ❌ | |
| Const enums | ✅ | ❌ | ✅ | ❌ | ❌ | |
| Unions & Intersections | Union types | ✅ | ✅ | ✅ | ✅ | ✅ |
| Discriminated unions | 🚀 | ✅ | ✅ | ✅ | ✅ | |
| Intersection types | ✅ | ✅ | ✅ | ✅ | ✅ | |
| Utility Types | Partial<T> | ✅ | ✅ | ✅ | ❌ | ✅ |
Required<T> | ✅ | ✅ | ✅ | ❌ | ✅ | |
Pick<T, K> | ✅ | ✅ | ✅ | ❌ | ✅ | |
Omit<T, K> | ✅ | ✅ | ✅ | ❌ | ✅ | |
Exclude<T, U> | ✅ | ❌ | ✅ | ❌ | ✅ | |
Extract<T, U> | ✅ | ❌ | ✅ | ❌ | ✅ | |
NonNullable<T> | ✅ | ✅ | ✅ | ❌ | ❌ | |
Awaited<T> | ✅ | ❌ | ✅ | ❌ | ✅ | |
Parameters<F> | ✅ | ❌ | ✅ | ❌ | ✅ | |
ReturnType<F> | ✅ | ❌ | ✅ | ❌ | ✅ | |
| String Utilities | Uppercase<S> | ⚠️ | ❌ | ✅ | ❌ | ✅ |
Lowercase<S> | ⚠️ | ❌ | ✅ | ❌ | ✅ | |
Capitalize<S> | ⚠️ | ❌ | ✅ | ❌ | ✅ | |
Uncapitalize<S> | ❌ | ❌ | ✅ | ❌ | ✅ | |
| Functions | Function types | 💎 | ✅ | ✅ | ❌ | ✅ |
| Method signatures | ✅ | ❌ | ✅ | ❌ | ❌ | |
| Call signatures | ✅ | ❌ | ✅ | ❌ | ❌ | |
| Rest parameters | ✅ | ✅ | ✅ | ❌ | ✅ | |
| Advanced | Circular references | ✅ | ❌ | ✅ | ❌ | ⚠️ |
| Generic types | ✅ | ✅ | ✅ | ❌ | ✅ | |
| Conditional types | ⚠️ | ❌ | ✅ | ❌ | ⚠️ | |
| Mapped types | ❌ | ❌ | ✅ | ❌ | ❌ | |
| Type inference | ❌ | ❌ | x | ❌ | ❌ |
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 | run-types | Zod | Typia | AJV | TypeBox |
|---|---|---|---|---|---|
| Core | |||||
| Type inference from TS | ✅ | ❌ | ✅ | ❌ | ❌ |
| Schema-first approach | ❌ | ✅ | ❌ | ✅ | ✅ |
| JIT compilation | ✅ | ❌ | AOT | ✅ | ✅ |
| TSC build required | ✅ | ❌ | ✅ | ❌ | ❌ |
| Validation | |||||
| Type validation | ✅ | ✅ | ✅ | ✅ | ✅ |
| Strict validation | ✅ | ✅ | ✅ | ✅ | ✅ |
| Error messages | ✅ | ✅ | ✅ | ✅ | ✅ |
| Custom error messages | ✅ | ✅ | ✅ | ✅ | ✅ |
| Serialization | |||||
| JSON serialization | ✅ | ❌ | ✅ | ❌ | ❌ |
| Binary serialization | ✅ | ❌ | PROTOBUF | ❌ | ❌ |
| Date handling | ✅ | ❌ | ✅ | ❌ | ✅ |
| BigInt handling | ✅ | ❌ | ✅ | ❌ | ✅ |
| Map/Set handling | ✅ | ❌ | ✅ | ❌ | ❌ |
| Other | |||||
| Mock data generation | ✅ | ❌ | ✅ | ❌ | ❌ |
| Function reflection | ✅ | ❌ | ❌ | ❌ | ❌ |
| AOT code generation | ✅ | ❌ | ✅ | ❌ | ✅ |
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
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
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.
✅ Use run-types when:
❌ Consider alternatives when:
at runtime