Skip to Content

Miscellaneous

Three small modules that share the typia transform but don’t fit anywhere else: misc (clone / prune / literals), notations (case conversion), and http (form data / query / headers / route parameters).

misc.clone β€” deep copy

signatures
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 invalid

The 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>>; }
examples/src/misc/assertClone.ts
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 β€” remove extra properties

signatures
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; returns false instead of mutating 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.

Caution

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).

examples/src/misc/assertPrune.ts
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 β€” union literal type β†’ array

signature
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.

examples/src/misc/literals.ts
import typia from "typia"; typia.misc.literals<"A" | "B" | "C" | 1 | 2n>();

notations β€” case conversion

Three case converters: camel, pascal, snake. Each one walks the object and rewrites property names to that case. Same four-variant family as everywhere else:

signatures β€” example for camelCase
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>>; }

PascalCase and SnakeCase swap in for CamelCase in the type. The output type is computed at the type level so the rest of your code knows about the new property names.

typia.notations.snake<{ userId: string; userName: string }>({ userId: "1", userName: "John", }); // β†’ { user_id: "1", user_name: "John" }
export namespace notations { export function camel<T>(input: T): CamelCase<T>; export function assertCamel<T>(input: T | unknown): CamelCase<T>; export function isCamel<T>(input: T | unknown): CamelCase<T> | null; export function validateCamel<T>(input: T | unknown): IValidation<CamelCase<T>>; // Same surface for pascal / Pascal and snake / Snake. // Each has create* factories too. }
examples/src/notations/camel.ts
import typia from "typia"; interface IPerson { is_my_name_samchon?: boolean; HelloTheNewWorld: string; ToHTML: string; } typia.notations.createCamel<IPerson>();

http β€” decode form data, query strings, headers, route params

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

signatures
namespace http { function query<T extends object>(input: string | URLSearchParams): Resolved<T>; function assertQuery<T extends object>(input: string | URLSearchParams): Resolved<T>; function isQuery<T extends object>(input: string | URLSearchParams): Resolved<T> | null; function validateQuery<T extends object>(input: string | URLSearchParams): IValidation<Resolved<T>>; }

http.query decodes a query string (or a URLSearchParams) into a typed object. Numeric and boolean properties are coerced from their string form automatically.

Restrictions (typia rejects at compile time):

  1. T must be an object type
  2. No dynamic keys
  3. Only boolean | bigint | number | string or arrays of those
  4. No unions

http.query itself doesn’t validate constraint tags (Format, Minimum, …). The assertQuery / isQuery / validateQuery variants do.

examples/src/http/query.ts
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

signatures
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:

  1. T must be an object type

  2. No dynamic keys

  3. Property keys must be lowercase (HTTP headers are case-insensitive; typia normalizes to lowercase)

  4. Property values may be undefined but not null

  5. Only boolean | bigint | number | string or arrays of those

  6. No unions

  7. set-cookie must be an array

  8. These headers cannot be array-typed (the HTTP spec collapses them to a single value):

    age, authorization, content-length, content-type, etag, expires, from, host, if-modified-since, if-unmodified-since, last-modified, location, max-forwards, proxy-authorization, referer, retry-after, server, user-agent

If you trip one of these rules, typia rejects the call at compile time with a clear error.

examples/src/http/headers.ts
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

signature
namespace http { function parameter<T extends boolean | bigint | number | string | null>(input: string): 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, there’s no isParameter or validateParameter β€” 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 string
examples/src/http/parameter.ts
import typia, { tags } from "typia"; typia.http.createParameter<string & tags.Format<"uuid">>(); typia.http.createParameter<number & tags.Type<"uint32">>();

http.formData β€” multipart form data

signature
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.

Where to go next

  • The full validator family β†’ is Β· assert Β· validate
  • Constraint tags on query/headers/parameter values β†’ Special Tags
  • Random data for tests β†’ random
  • NestJS integration that builds on http.* β†’ NestiaΒ 
Last updated on