Code Monkey home page Code Monkey logo

typia's Introduction

Typia

Typia Logo

GitHub license npm version Downloads Build Status Guide Documents

// RUNTIME VALIDATORS
export function is<T>(input: unknown): input is T; // returns boolean
export function assert<T>(input: unknown): T; // throws TypeGuardError
export function assertGuard<T>(input: unknown): asserts input is T;
export function validate<T>(input: unknown): IValidation<T>; // detailed

// JSON FUNCTIONS
export namespace json {
    export function application<T>(): IJsonApplication; // JSON schema
    export function assertParse<T>(input: string): T; // type safe parser
    export function assertStringify<T>(input: T): string; // safe and faster
}

// PROTOCOL BUFFER
export namespace protobuf {
    export function message<T>(): string; // Protocol Buffer message
    export function assertDecode<T>(buffer: Uint8Array): T; // safe decoder
    export function assertEncode<T>(input: T): Uint8Array; // safe encoder
}

// RANDOM GENERATOR
export function random<T>(g?: Partial<IRandomGenerator>): T;

Typia is a transformer library supporting below features:

  • Super-fast Runtime Validators
  • Enhanced JSON functions
  • Protocol Buffer encoder and decoder
  • Random data generator

Note

  • Only one line required, with pure TypeScript type
  • Runtime validator is 20,000x faster than class-validator
  • JSON serialization is 200x faster than class-transformer

Sponsors

Thanks for your support.

Your donation encourages typia development.

Sponsers

Playground

You can experience how typia works by playground website:

Guide Documents

Check out the document in the website:

🏠 Home

πŸ“– Features

πŸ”— Appendix

typia's People

Contributors

8471919 avatar dependabot[bot] avatar djawnstj avatar elob avatar enghitalo avatar ghlin avatar green1052 avatar jochongs avatar jongwooo avatar kakasoo avatar kristjantammekivi avatar le2sky avatar lemon-mint avatar limejuny avatar logico-philosophical avatar lorenzhenk avatar ltnscp9028 avatar luncliff avatar mararmar avatar mbm1607 avatar qpakzk avatar rojiwon123 avatar samchon avatar seo-rii avatar sinclairzx81 avatar sk-fcomputer avatar sunrabbit123 avatar techvlad avatar utilforever avatar xvezda avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

typia's Issues

Support description comments

When descriptive comments are written on the type, revive in onto the JSON schema.

Descripted Type

/**
 * Member information.
 */
interface IMember
{
    /**
     * Primary Key.
     */
    id: string | null;

    /**
     * Email address.
     */
    email: String;

    /**
     * Real name.
     */
    name: string;

    /**
     * Sex of the member.
     */
    sex: "male" | "female" | 1 | 2 | null;

    /**
     * Age, but omittable.
     */
    age: number | null;

    /**
     * Is dead or alive.
     */
    dead: boolean | null;
}

Transformed code

const stringify = src_1.default.createStringifier(() => ({
    "schema": {
        "$ref": "components#/schemas/IMember"
    },
    "components": {
        "schemas": {
            "IMember": {
                "$id": "IMember",
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "nullable": true,
                        "description": "Primary Key."
                    },
                    "email": {
                        "type": "string",
                        "nullable": false,
                        "description": "Email address."
                    },
                    "name": {
                        "type": "string",
                        "nullable": false,
                        "description": "Real name."
                    },
                    "sex": {
                        "oneOf": [
                            {
                                "type": "number",
                                "nullable": true,
                                "description": "Sex of the member."
                            },
                            {
                                "type": "string",
                                "nullable": true,
                                "description": "Sex of the member."
                            }
                        ]
                    },
                    "age": {
                        "type": "number",
                        "nullable": true,
                        "description": "Age, but omittable."
                    },
                    "dead": {
                        "type": "boolean",
                        "nullable": true,
                        "description": "Is dead or alive."
                    }
                },
                "nullable": false,
                "required": [
                    "id",
                    "email",
                    "name",
                    "sex",
                    "age",
                    "dead"
                ],
                "description": "Member information."
            }
        }
    }
}));

Cannot understand when generic Array alias type comes

When generic Array alias type comes, typescript-json understands it as an object who has only the length: number property.

Therefore, study the TypeScript Compiler AST again and find solution for the special case.

{
    when_generic_array_alias_type_comes: {
        type: "object",
        properties: {
            length: {
                type: "number",
                nullable: false
            }
        },
        nullable: false,
        required: [
            "length"
        ]
    }
}

Bug when template literal type on generic

Summary

When template library type be used in the generic argument, it becomes an error.

  • SDK Version: 2.1.5
  • Expected behavior: No problem
  • Actual behavior: Becomes invliad uri format
Error: schema is invalid: data/$ref must match format "uri-reference"

Code occuring the bug

import TSON from "typescript-json";

interface IPointer<T> {
    value: T;
}
TSON.stringify<IPointer<`some${string}`>>(input);

Refactor factories

Design those structures and let factories to return them:

  • IJsonApplication
  • IJsonComponents
  • IJsonSchema

Give up using the JSON schema and go my own way

The JSON schema and its related libraries like fast-json-stringify or ajv never can solve the #28 problem.

Therefore, give up using the JSON schema and implement the faster JSON.stringify() function by myself.

The my new way will solve the #28 problem and would be much faster than fast-json-stringify.

When `Object.toJSON()` returns atomic value, it always be the `null`.

Analyzing the fast-json-stringify library, I found the reason why those test function occur erros.

The reason was on return type of the Object.JSON() methods in those test functions. All of them are returning the atomic value and fast-json-stringify does only calls the Object.JSON() method when the JSON schema type is object. In such reason, atomic typed JSON schema like below test codes occurs the JSON string conversion error.

Therefore, when Object.toJSON() returns an atomic typed value, just use the JSON.stringify() function.

Try to replace core library from `fast-json-stringify` to the `ajv`.

The ajv supports not only stringify but parse function, too.

Therefore, make a new branch features/ajv and try to replace core library from fast-json-stringify to the ajv.

If the ajv is enough suitable like the fast-json-stringify, provide the mode option to select the core library.

Naming convension of the `components.schemas`

Name of the components.schemas to follow its origin type name and add incremental value only when duplicated type name exists.

However, as the JSON schema pointer needs duplicate definition for both nullable and non-nullable types, the naming convension always include the nullable symbol like ISystem.ICommit.NonNullable. Also, when a target type has < and > syntax because it has generic parameter(s), change the < and > words to be compatible with URL patterns by replacing keywords.

Refactor `MetadataFactory` to be reusable

samchon/nestia#68

My another library nestia is planning to build the swagger.json and the swagger.json also utilizes the JSON schema, too. Therefore, refactor MetadataFactory to be reusable. Also, pointer address of the fast-json-stringify and swagger.json is different, therefore refactor the MetadataFactory to be compatible for them.

Support implicit generic argument for the `TSON.stringify()`

This should be possible:

import TSON from "typescript-json";
import { RandomGenerator } from "../internal/RandomGenerator";

export function test_stringify_object_implicit(): void
{
    const lecture: ILecture = {
        name: RandomGenerator.string(),
        professor: RandomGenerator.string(),
        grade: RandomGenerator.number()
    };
    const implicit: string = TSON.stringify(lecture);
    const explicit: string = TSON.stringify<ILecture>(lecture);
}

interface ILecture
{
    name: string;
    professor: string;
    grade: number;
}

Add benchmark program

Benchmark for real use cases.

Also, the benchmark program would not compare only with JSON.stringify() and TSON.stringify(). It would compare a manual programmed JSON string conversion function, who would be generated by the v3. Therefore, the benchmark program would be composed like below:

Type JSON.stringify() TSON.stringify() v2 TSON.stringify() v3

Fill the `required` field of the JSON schema.

When such interface has been targeted,

interface ILecture
{
    name: string;
    professor?: string | number;
    grade: number | undefined;
}

JSON schema must represent the optional (undefindable) property through the required field.

{
    type: "object",
    properties: {
        name: {
            type: "string",
            nullable: false
        },
        professor: {
            anyOf: [
                {
                    type: "string",
                    nullable: false
                },
                {
                    type: "number",
                    nullable: false
                }
            ]
        },
        grade: {
            type: "number",
            nullable: false
        }
    },
    nullable: false,
    required: [
        "name"
    ]
}

Refactor `JsonFactory` and `SchemaFactory`

Refactor JsonFactory and SchemaFactory to be much effiently. Especially, the JsonFactory code is too complicate and inefficient as it has hard coded to build the ts.Exression only for the fast-json-stringify Schema. I think creating a new ExpressionFactory who can use every typed value would be much powerful and efficient. Maybe, its code would be even much shorter than the JsonFactory

Therefore, rename the SchemaFactory to the MetadataFactory and separate the JsonFactory to the SchemaFactory and ExpressionFactory, who converts IMetadata to JSON schema and converts any instance to the ts.Expression.

Use `oneOf` instead of the `anyOf`

When union type comes, there's no difference between them, only within framework of the JSON.stringify() function booster.

However, when user of this typescript-json imports the SchemaFactory by itself, it would be a matter, as oneOf is the exact use case for that union type. Therefore, change the SchemaFactory to use the oneOf statement instead of the anyOf

μ•„ν‚€λ“œλ‘œμš° TypeScript/ν”„λ‘ νŠΈ 개발자 μ±„μš©

저희 νšŒμ‚¬ "μ•„ν‚€λ“œλ‘œμš°" μ—μ„œ, μ‚Όμ΄Œκ³Ό ν•¨κ»˜ 일할 ν”„λ‘ νŠΈ 개발자 뢄듀을, 졜고의 λŒ€μš°λ‘œ λͺ¨μ‹­λ‹ˆλ‹€.

"μ•„ν‚€λ“œλ‘œμš°" λŠ” 3D (μΈν…Œλ¦¬μ–΄) 에디터 및 이에 κ΄€ν•œ νŒŒμƒ μ†”λ£¨μ…˜λ“€μ„ λ§Œλ“œλŠ” νšŒμ‚¬μž…λ‹ˆλ‹€. λ‹€λ§Œ 저희 νšŒμ‚¬μ˜ μ£Όλ ₯ μ œν’ˆμ΄ 3D 에디터라 ν•˜μ—¬, λ°˜λ“œμ‹œ 3D 내지 λžœλ”λ§μ— λŠ₯μˆ™ν•΄μ•Ό ν•˜λŠ” 것은 μ•„λ‹ˆλ‹ˆ, 일반적인 ν”„λ‘ νŠΈ κ°œλ°œμžλΆ„λ“€λ„ λ§μ„€μž„μ—†μ΄ μ§€μ›ν•΄μ£Όμ‹­μ‹œμ˜€.

그리고 저희 νšŒμ‚¬λŠ” λΆ„μœ„κΈ°κ°€ λ‹€λ“€ μΉœν•˜κ³  즐겁게 μ§€λ‚΄λŠ” λΆ„μœ„κΈ°μž…λ‹ˆλ‹€. λ”ν•˜μ—¬ μœ„ typescript-json μ΄λ‚˜ nestia 및 payments λ“±, μ œλ²• 합리적(?)이고 μž¬λ―Έλ‚œ ν”„λ‘œμ νŠΈλ“€μ„ λ‹€μ–‘ν•˜κ²Œ μ²΄ν—˜ν•΄λ³΄μ‹€ 수 μžˆμŠ΅λ‹ˆλ‹€.

  • νšŒμ‚¬μ†Œκ°œμ„œ: archidraw.pdf
  • 기술 μŠ€νƒ: React + TypeScript
  • 이λ ₯μ„œ: 자유 양식
  • μ§€μ›μ²˜: [email protected]

`IJsonComponent.IObject.required` to be optional

When using TSON.createSchema() for the swagger.json generation, empty valued IJsonComponent.IObject.required becomes an error (warning level). No matter to building entire swagger.json, but the error message seems annoying. Therefore, change the IJsonComponent.IObject.required type to be optional and make it to be undefined for the empty array.

Try the `compile-json-stringify` too.

Reading the compile-json-stringify documents, it seems much faster than fast-json-stringify and ajv when object.

Therefore, also try the compile-json-stringify, too.

If it 's also suitable, provide mode option who can select the core library.

Support `$recursiveAnchor` and `$recursiveRef` tag

To support such complicate union and recursive type, $recursiveAnchor and $recursiveRef` must be supported.

Without supporting those tags, one of below erros would be occured:

  • Error: schema with key or id "IDirectory" already exists bug
  • MissingRefError: can't resolve reference components#/schemas/IDirectory from id IDirectory
// BUCKET & DIRECTORY
type IBucket = IDirectory | IFile;
namespace IBucket
{
    export interface IBase<Type extends string>
    {
        type: Type;
        id: string;
        name: string;
    }
}
interface IDirectory extends IBucket.IBase<"directory">
{
    children: IBucket[];
}

// FILES
type IFile = IImageFile | ITextFile | IZipFile;
namespace IFile
{
    export interface IBase<Extension extends string>
        extends IBucket.IBase<"file">
    {
        extension: Extension;
        size: number;
    }
}
interface IImageFile
    extends IFile.IBase<"jpg"|"png"|"gif">
{
    width: number;
    height: number;
    url: string;
}
interface ITextFile
    extends IFile.IBase<"txt"|"md"|"ts">
{
    content: string;
}
interface IZipFile
    extends IFile.IBase<"zip">
{
    files: number;
}

New function `createApplication<T>(): IJsonApplication`

Create a new facade function that returning JSON schema and components.

/**
 * JSON Schema Application.
 * 
 * Creates a JSON schema application which contains both main JSON schema and components. 
 * Note that, all of the object types are stored in the {@link IJsonApplication.components} 
 * property for the `$ref` referencing.
 * 
 * @template T Target type
 * @return JSON schema application
 * @author Samchon
 */
export function createApplication<T>(): IJsonApplication;

Literal named property in the Object causes error

Bug Report

Note that, the bug you're reporting may have registered in the issues by another user. Even the bug you're reporting may have been fixed in the @next version. In such reasons, I recommend you to check the old issues and reproduct your code with the @next version before publishing the bug reporting issue.

`npm install --save-dev typescript-json@next`

When the same error occurs even in the @next version, then please fill the below template:

Summary

When a literal named property from an object type comes, it becomes a runtime error.

  • SDK Version: 2.1.0-dev.20220505
  • Expected behavior:
  • Actual behavior:

Write detailed description in here.

Error: ""something-interesting-do-you-want?"" is required!

Code occuring the bug

import TSON from "typescript-json";

export function test_stringify_object_literal_property()
{
    const property: ILiteralProperty = {
        "something-interesting-do-you-want?": "what's that",
        "or-something-crazy-do-you-want?": "nope"
    };
    const json: string = TSON.stringify(property);
    const expected: string = JSON.stringify(property);

    if (json !== expected)
        throw new Error("Bug on TSON.stringify(): failed to understand the object literal property.");
}

interface ILiteralProperty
{
    "something-interesting-do-you-want?": string;
    ["or-something-crazy-do-you-want?"]: string;
}

Support generic typed object and its alias types

Like below example cases, when generic typed object or its alias type comes, typescript-json cannot parse the generic typed properties and considers them as the unknown type. Therefore, no error be occured, but the JSON string conversion speed is not fast, either.

Generic typed object

import TSON from "../../src";

export function test_stringify_object_generic_alias(): void
{
    const something: ISomething<string> = {
        value: "value",
        child: {
            child_value: "child_value",
            child_next: "child_next"
        },
        elements: ["one", "two", "three"],
    };
    const json: string = TSON.stringify<ISomething<string>>(something);
    const expected: string = JSON.stringify(something);

    if (json !== expected)
        throw new Error("Bug on TSON.stringify(): failed to understand the generic object type.");
}

interface ISomething<T>
{
    value: T;
    child: IChild<T>;
    elements: T[];
}
interface IChild<U>
{
    child_value: U;
    child_next: U;
}

Generic alias type of the generic typed object

import TSON from "../../src";
import { Primitive } from "../internal/Primitive";

export function test_stringify_object_generic_alias(): void
{
    const alias: Alias = {
        value: "Something"
    };
    const stringify: (input: Alias) => string = TSON.createStringifier<Alias>();
    
    const json: string = stringify(alias);
    const parsed: Alias = JSON.parse(json);

    if (Primitive.equal_to(alias, parsed) === false)
        throw new Error("Bug on TSON.createStringifier(): failed to understand the object alias type.");
}

interface ISomething<T>
{
    value: T;
}
type Alias = ISomething<string>;

Write community documents

Write community documents:

  • issue templates
    • bug report
    • feature request
    • question
  • pull request template
  • code of conduct
  • contributing

[V3] faster `JSON.stringify()` function by myself

Implement faster JSON.stringify() function by myself.

It would be v3 update and its JSON string conversion speed would be much faster than v2. The JSON string conversion speed would be 3x times faster than before (would be thoundands times faster when considering the optimizer plannig time). Also, the v3 does not utilize the JSON schema, but TypeScript type directly. Therefore, typescript-json would be much safer than ordinary v2.


typescript-json is wrapper library of fast-json-stringify, which can omit JSON schema definition, through the TypeScript Compiler API with transformer. In such reason, providing maximum convenience to users with minimum effort was possible, by developing an automatic JSON schema generator. Furthermore, as typescript-json could define JSON schema automatically, dependent library like nestia could build swagger.json very easily.

However, as adopted fast-json-stringify, typescript-json is following its disadvantages, too.

At 1st, fast-json-stringify is not fast.

The fast-json-stringify requires too much time to constructing faster JSON string conversion function. It analyzes JSON schema at runtime, therefore optimizing the JSON string conversion plan time is required, and it outcomes below result. As you can see from the below graph, optimizer planning time makes fast-json-stringify slower, than the native JSON.stringify(), about hundres times. Even measuring only JSON conversion speed, fast-json-stringify is slow too, when recursive relationshp comes.

However, if I change typescript-json to optimize the JSON string conversion plan in the compilation level, through the TypeScript Compiler API with transformer, the conversion speed would not be slow by constructing the optimizer plan. Also, as typescript-json knows exact type of the target data, optimizer plan would be much evolved than before.

Include optimizer planning time Only JSON string conversion time
image image

At 2nd, fast-json-stringify is not enough stable.

fast-json-stringify is utilizing ajv library as dependency and the ajv library occurs an error when composite structured object type comes. Even the ajv is using non-standard feature $recursiveRef, which does not defined in the JSONS schema. However, the $recursiveRef be broken when complicated structure comes.

However, if I develop JSON string conversion logic by myself, such bug would not be occured.

At last, TypeScript type is much superior than the JSON schema.

Developing the JSON schema generator from the TypeScript type, I understood that how TypeScrip type is superior and how JSON schema is inferior, within framework of the TypeScript user. Therefore, when developing TypeScript library boosting up the JSON string conversion speed, using pure TypeScript type is much better.

For example, fast-json-stringify and ajv cannot understand the Object.toJSON() method, because they don't know original types of parameters. With fast-json-stringify, to solve the below bug, custom JSON string conversion must check all of the values whether they're a type of object and has a toJSON() method or not, via recursive visit strategy. However, it would make JSON string conversion speed much slower.

However, if v3 comes, the toJSON() methods would be exactly traced in the compilation level.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.