Miscellaneous
Four small modules that share the typia transform but don’t fit anywhere else: misc (clone / prune / literals), notations (case conversion), http (form data / query / headers / route parameters), and reflect (type metadata introspection).
misc.clone
namespace misc {
function clone<T>(input: T): Resolved<T>;
function assertClone<T>(input: unknown): Resolved<T>; // + assert
function isClone<T>(input: unknown): Resolved<T> | null; // + is
function validateClone<T>(input: unknown): IValidation<Resolved<T>>; // + validate
}Same family pattern as the validators — clone trusts you, the others wrap the copy with type checking.
const copy = typia.misc.clone<User>(user);
// Type-safe variants
const maybe = typia.misc.isClone<User>(input); // null if `input` isn't a User
const result = typia.misc.validateClone<User>(input); // IValidation<User>
const checked = typia.misc.assertClone<User>(input); // throws if invalidThe pairing rule is the same as elsewhere:
misc.isClone<T>=is<T>+clone<T>misc.assertClone<T>=assert<T>+clone<T>misc.validateClone<T>=validate<T>+clone<T>
undefined
export namespace misc {
export function clone<T>(input: T): Resolved<T>;
export function assertClone<T>(input: T | unknown): Resolved<T>;
export function isClone<T>(input: T | unknown): Resolved<T> | null;
export function validateClone<T>(input: T | unknown): IValidation<Resolved<T>>;
// Factories (Resolved<T> = T projected for the JS runtime)
export function createClone<T>(): (input: T) => Resolved<T>;
export function createAssertClone<T>(): (input: T | unknown) => Resolved<T>;
export function createIsClone<T>(): (input: T | unknown) => Resolved<T> | null;
export function createValidateClone<T>(): (input: T | unknown) => IValidation<Resolved<T>>;
}TypeScript Source
import typia from "typia";
const department: IDepartment = typia.random<IDepartment>();
const cloned: IDepartment = typia.misc.assertClone<IDepartment>(department);
console.log(cloned);
interface IDepartment {
/** @format uuid */
id: string;
/** @minLength 3 */
name: string;
/** @type int */
limit: number;
clerks: IClerk[];
}
interface IClerk {
name: string;
/**
* @exclusiveMinimum 19
* @maximum 100
*/
age: number;
authority: number;
/** @format date */
joined_at: string;
}misc.prune
namespace misc {
function prune<T>(input: T): void; // mutates input
function assertPrune<T>(input: unknown): T; // + assert, then mutates
function isPrune<T>(input: unknown): input is T; // + is; prunes & returns true on match, false (no mutation) on mismatch
function validatePrune<T>(input: unknown): IValidation<T>; // + validate
}prune and assertPrune walk the input object and delete any property not declared on T — they mutate input in place. prune returns void; assertPrune returns the now-mutated input typed as T. The isPrune and validatePrune variants only mutate once they’re sure the input matches T, so they’re safe on values you weren’t expecting.
If you need a non-mutating version, clone first: typia.misc.prune<T>(typia.misc.clone<T>(value)).
typia.misc.prune<User>(input);
// input is now narrowed in place — extra properties removed.
const cleaned = typia.misc.assertPrune<User>(input);
// Same, but throws if input doesn't match User. Returns input.
if (typia.misc.isPrune<User>(input)) {
// input is User and has been pruned. `input` is now typed as User.
}
const r = typia.misc.validatePrune<User>(input);
// r.success === true means input was a User and is now pruned.Useful when you receive a JSON document with extra fields you’d rather not pass around (e.g. logging, persisting to a DB that’s strict about schema).
TypeScript Source
import typia from "typia";
const department: IDepartment = typia.random<IDepartment>();
const pruned: IDepartment = typia.misc.assertPrune<IDepartment>(department);
console.log(pruned);
interface IDepartment {
/** @format uuid */
id: string;
/** @minLength 3 */
name: string;
/** @type int */
limit: number;
clerks: IClerk[];
}
interface IClerk {
name: string;
/**
* @exclusiveMinimum 19
* @maximum 100
*/
age: number;
authority: number;
/** @format date */
joined_at: string;
}misc.literals
namespace misc {
function literals<T extends boolean | number | string | bigint | null>(): T[];
}If you have a string-literal union ("red" | "green" | "blue") and you want the runtime array ["red", "green", "blue"] to iterate over, misc.literals reads the union from the TS type and emits the array.
Handy for select-box options, discriminated-union test matrices, etc.
TypeScript Source
import typia from "typia";
typia.misc.literals<"A" | "B" | "C" | 1 | 2n>();notations
Four case converters: camel, pascal, snake, kebab. Each one walks the object and rewrites property names to that case at type and runtime. Same four-variant family as everywhere else (name, assertName, isName, validateName, plus create* factories).
camel
namespace notations {
function camel<T>(input: T): CamelCase<T>;
function assertCamel<T>(input: unknown): CamelCase<T>;
function isCamel<T>(input: unknown): CamelCase<T> | null;
function validateCamel<T>(input: unknown): IValidation<CamelCase<T>>;
}typia.notations.camel<{ user_id: string; user_name: string }>({
user_id: "1",
user_name: "John",
});
// → { userId: "1", userName: "John" }TypeScript Source
import typia from "typia";
interface IPerson {
is_my_name_samchon?: boolean;
HelloTheNewWorld: string;
ToHTML: string;
}
typia.notations.createCamel<IPerson>();pascal
namespace notations {
function pascal<T>(input: T): PascalCase<T>;
function assertPascal<T>(input: unknown): PascalCase<T>;
function isPascal<T>(input: unknown): PascalCase<T> | null;
function validatePascal<T>(input: unknown): IValidation<PascalCase<T>>;
}TypeScript Source
import typia from "typia";
interface IPerson {
is_my_name_samchon?: boolean;
helloTheNewWorld: string;
toHTML: string;
}
typia.notations.createPascal<IPerson>();snake
namespace notations {
function snake<T>(input: T): SnakeCase<T>;
function assertSnake<T>(input: unknown): SnakeCase<T>;
function isSnake<T>(input: unknown): SnakeCase<T> | null;
function validateSnake<T>(input: unknown): IValidation<SnakeCase<T>>;
}typia.notations.snake<{ userId: string; userName: string }>({
userId: "1",
userName: "John",
});
// → { user_id: "1", user_name: "John" }TypeScript Source
import typia from "typia";
interface IPerson {
isMyNameSamchon?: boolean;
HelloTheNewWorld: string;
ToHTML: string;
}
typia.notations.createSnake<IPerson>();kebab
namespace notations {
function kebab<T>(input: T): KebabCase<T>;
function assertKebab<T>(input: unknown): KebabCase<T>;
function isKebab<T>(input: unknown): KebabCase<T> | null;
function validateKebab<T>(input: unknown): IValidation<KebabCase<T>>;
}typia.notations.kebab<{ userId: string; user_name: string }>({
userId: "1",
user_name: "John",
});
// → { "user-id": "1", "user-name": "John" }kebab derives the snake_case form first and then rewrites the word separators to hyphens, keeping leading underscores untouched.
TypeScript Source
import typia from "typia";
interface IPerson {
isMyNameSamchon?: boolean;
HelloTheNewWorld: string;
ToHTML: string;
}
typia.notations.createKebab<IPerson>();http
The http module turns HTTP-shaped inputs (URLSearchParams, headers object, route parameter strings, FormData) into typed objects, with automatic string-to-number / string-to-boolean coercion.
http.query — URL query strings
namespace http {
function query<T extends object>(input: string | IReadableURLSearchParams): Resolved<T>;
function assertQuery<T extends object>(input: string | IReadableURLSearchParams): Resolved<T>;
function isQuery<T extends object>(input: string | IReadableURLSearchParams): Resolved<T> | null;
function validateQuery<T extends object>(input: string | IReadableURLSearchParams): IValidation<Resolved<T>>;
}http.query decodes a query string (or any IReadableURLSearchParams-shaped object — the standard URLSearchParams works, as does Hono’s and other duck-typed shims) into a typed object. Numeric and boolean properties are coerced from their string form automatically.
Restrictions (typia rejects at compile time):
Tmust be an object type- No dynamic keys
- Only
boolean | bigint | number | stringor arrays of those - No unions
http.query itself doesn’t validate constraint tags (Format, Minimum, …). The assertQuery / isQuery / validateQuery variants do.
TypeScript Source
import typia from "typia";
interface IQuery {
limit?: number;
enforce: boolean;
values?: string[];
atomic: string | null;
indexes: number[];
}
typia.http.createQuery<IQuery>();http.headers — HTTP request headers
namespace http {
function headers<T extends object>(
input: Record<string, string | string[] | undefined>,
): Resolved<T>;
// …assert / is / validate variants
}http.headers decodes an Express/Fastify-style headers object. Same coercion as query, plus a stricter set of restrictions specific to HTTP:
-
Tmust be an object type -
No dynamic keys
-
Property keys must be lowercase (HTTP headers are case-insensitive; typia normalizes to lowercase)
-
Property values may be
undefinedbut notnull -
Only
boolean | bigint | number | stringor arrays of those -
No unions
-
set-cookiemust be an array -
These headers cannot be array-typed (the HTTP spec mandates a single value):
ageauthorizationcontent-lengthcontent-typeetagexpiresfromhostif-modified-sinceif-unmodified-sincelast-modifiedlocationmax-forwardsproxy-authorizationrefererretry-afterserveruser-agent
If you trip one of these rules, typia rejects the call at compile time with a clear error.
TypeScript Source
import typia from "typia";
interface IHeaders {
"x-Category": "x" | "y" | "z";
"x-MEMO"?: string;
"x-nAmE"?: string;
"x-Values": number[];
"x-FlAgS": boolean[];
"X-Descriptions": string[];
}
typia.http.createHeaders<IHeaders>();http.parameter — URL path parameters
namespace http {
function parameter<T extends boolean | bigint | number | string | null>(input: string): Resolved<T>;
}http.parameter decodes a single URL path parameter (a string from :id in your route) into the expected primitive type, and always asserts. Unlike query / headers / formData, there is no isParameter, validateParameter, or createParameter — a single path-parameter string is either parseable into T or it isn’t, so typia exposes only the asserting form. If the value doesn’t match T, it throws TypeGuardError.
const id: number = typia.http.parameter<number>(request.params.id);
// throws if `request.params.id` isn't a valid number stringTypeScript Source
import typia, { tags } from "typia";
typia.http.createParameter<string & tags.Format<"uuid">>();
typia.http.createParameter<number & tags.Type<"uint32">>();http.formData — multipart form data
namespace http {
function formData<T extends object>(input: FormData): Resolved<T>;
// …assert / is / validate variants
}http.formData decodes a FormData instance into a typed object. Allowed property types: boolean | bigint | number | string | Blob | File or arrays of those.
reflect
namespace reflect {
function schema<Type>(): IMetadataSchemaUnit;
function schemas<Types extends unknown[]>(): IMetadataSchemaCollection;
function name<T, Regular extends boolean = false>(): string;
}reflect exposes typia’s own type representation — the metadata every other feature (validators, JSON schema, protobuf, random, LLM schemas) is compiled from. Where typia.json.schemas flattens a type into JSON Schema, reflect.schema hands you the lossless internal form: unions stay buckets, optionality/nullability stay flags, and type tags keep their validation expressions.
reflect.schema / reflect.schemas
reflect.schema<T>() returns an IMetadataSchemaUnit: the schema of the target type plus a components dictionary holding every named object, alias, array, and tuple definition it references (recursive types reference themselves through here). reflect.schemas<[A, B]>() is the multi-type variant returning an IMetadataSchemaCollection with one entry per type over a shared components.
An IMetadataSchema is a union of buckets with top-level flags:
| Member | Meaning |
|---|---|
required / optional / nullable / any | undefined · ? modifier · null · any participation |
atomics | primitive members (boolean, bigint, number, string), each with its type-tag matrix |
constants | literal members, grouped by base type |
templates | template literal members |
arrays / tuples / objects / aliases | references into components by name |
natives | built-in classes (Date, Uint8Array, …) |
sets / maps / functions / escaped / rest | Set · Map · function members · toJSON() projection · variadic tuple rest |
Type tags survive with full fidelity — for string & tags.Format<"uuid"> the atomic’s tag matrix carries the kind, the JSON-schema fragment, and the validation expression:
typia.reflect.schema<IMember>();
interface IMember {
id: string & tags.Format<"uuid">;
age: number;
parent: IMember | null;
}export const unit = {
schema: { objects: [{ name: "IMember", tags: [] }], required: true, ... },
components: {
objects: [{
name: "IMember",
properties: [
{
key: { constants: [{ type: "string", values: [{ value: "id" }] }], ... },
value: {
atomics: [{
type: "string",
tags: [[{
kind: "format",
name: 'Format<"uuid">',
schema: { format: "uuid" },
validate: '$importInternal("isFormatUuid")($input)',
...
}]],
}],
...
},
},
// age: { atomics: [{ type: "number" }] }, parent: { objects: [IMember], nullable: true }
],
}],
aliases: [], arrays: [], tuples: [],
},
};Everything is a plain literal embedded at compile time — there is no runtime reflection cost, and the result is JSON.stringify-able as-is.
reflect.name
reflect.name<T>() embeds the display name typia uses for T in error messages and component keys:
typia.reflect.name<IMember[]>(); // "IMember[]"
typia.reflect.name<{ value: string } | null>(); // "{ value: string } | null"Use it when correlating TypeGuardError.expected / IValidation.IError.expected strings, or components entries from reflect.schema, back to your own types.