Skip to content

Commit

Permalink
Merge pull request #204 from samchon/v3.2
Browse files Browse the repository at this point in the history
Fix #203 - export `IValidation`
  • Loading branch information
samchon authored Sep 23, 2022
2 parents b942b33 + c45bdbb commit 4d4a68f
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 20 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "typescript-json",
"version": "3.2.7",
"version": "3.2.8",
"description": "Runtime type checkers and 5x faster JSON.stringify() function",
"main": "lib/index.js",
"typings": "lib/index.d.ts",
Expand Down
1 change: 1 addition & 0 deletions src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export * from "./schemas/IJsonApplication";
export * from "./schemas/IJsonComponents";
export * from "./schemas/IJsonSchema";
export * from "./TypeGuardError";
export * from "./IValidation";

/* -----------------------------------------------------------
BASIC VALIDATORS
Expand Down
32 changes: 16 additions & 16 deletions src/schemas/IJsonSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,23 @@ import { IMetadataTag } from "../metadata/IMetadataTag";

import { Atomic } from "../typings/Atomic";

export type IJsonSchema =
| IJsonSchema.IEnumeration<"boolean">
| IJsonSchema.IEnumeration<"number">
| IJsonSchema.IEnumeration<"bigint">
| IJsonSchema.IEnumeration<"string">
| IJsonSchema.IBoolean
| IJsonSchema.INumber
| IJsonSchema.IBigInt
| IJsonSchema.IString
| IJsonSchema.IArray
| IJsonSchema.ITuple
| IJsonSchema.IReference
| IJsonSchema.IRecursiveReference
| IJsonSchema.IOneOf
| IJsonSchema.IUnkown;

export type IJsonSchema = IJsonSchema.NotUnknown | IJsonSchema.IUnkown;
export namespace IJsonSchema {
export type NotUnknown =
| IEnumeration<"boolean">
| IEnumeration<"number">
| IEnumeration<"bigint">
| IEnumeration<"string">
| IBoolean
| INumber
| IBigInt
| IString
| IArray
| ITuple
| IOneOf
| IReference
| IRecursiveReference;

export interface IEnumeration<Type extends Atomic.Literal>
extends IAtomic<Type> {
enum: Array<Atomic.Mapper[Type]>;
Expand Down
68 changes: 65 additions & 3 deletions src/schemas/JsonTypeChecker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import { IJsonSchema } from "./IJsonSchema";
export class JsonTypeChecker {
public constructor(public readonly application: IJsonApplication) {}

/* -----------------------------------------------------------
GETTERS
----------------------------------------------------------- */
public getObject(key: string): IJsonComponents.IObject | undefined;
public getObject(schema: IJsonSchema.IReference): IJsonComponents.IObject;
public getObject(
Expand Down Expand Up @@ -43,14 +46,17 @@ export class JsonTypeChecker {
return found;
}

/* -----------------------------------------------------------
SPECIALIZERS
----------------------------------------------------------- */
public isOneOf(schema: IJsonSchema): schema is IJsonSchema.IOneOf;
public isOneOf(schema: IJsonSchema.IOneOf): boolean {
return Array.isArray(schema.oneOf);
}

public isUnknown(schema: IJsonSchema): schema is IJsonSchema.IUnkown;
public isUnknown(schema: IJsonSchema.IUnkown): boolean {
return Object.keys(schema).length === 0;
public isNotUnknown(schema: IJsonSchema): schema is IJsonSchema.NotUnknown;
public isNotUnknown(schema: IJsonSchema.IUnkown): boolean {
return Object.keys(schema).length !== 0;
}

public isAtomic(
Expand Down Expand Up @@ -112,4 +118,60 @@ export class JsonTypeChecker {
): schema is IJsonSchema.IRecursiveReference {
return schema.$recursiveRef !== undefined;
}

/* -----------------------------------------------------------
PREDICATORS
----------------------------------------------------------- */
public intersects(x: IJsonSchema, y: IJsonSchema): boolean {
// WHEN ANY TYPE
if (!this.isNotUnknown(x) || !this.isNotUnknown(y)) return true;

// ITERATE UNION TYPES
if (this.isOneOf(x)) return x.oneOf.some((x) => this.intersects(x, y));
else if (this.isOneOf(y))
return y.oneOf.some((y) => this.intersects(x, y));

// OBJECT TYPE
if (
(this.isReference(x) || this.isRecursiveReference(x)) !==
(this.isRecursiveReference(y) || this.isRecursiveReference(y))
)
return false;
else if (
this.isReference(x) ||
this.isRecursiveReference(x) ||
this.isReference(y) ||
this.isRecursiveReference(y)
)
return this._Intersects_of_objects(
this.getObject(x as any)!,
this.getObject(y as any)!,
);
else if (x.nullable === true && y.nullable === true) return true;
else if (x.type !== y.type) return false;

// ARRAY OR TUPLE TYPE
if (this.isArray(x) !== this.isArray(y)) return false;
else if (this.isArray(x) && this.isArray(y))
return this.intersects(x.items, y.items);
else if (this.isTuple(x) !== this.isTuple(y)) return false;
else if (this.isTuple(x) && this.isTuple(y))
return x.items.some((a) =>
y.items.some((b) => this.intersects(a, b)),
);

// ATOMIC OR LITERAL TYPE
if (!this.isEnumeration(x) || !this.isEnumeration(y)) return true;
return x.enum.some((a) => y.enum.some((b) => a === b));
}

private _Intersects_of_objects(
x: IJsonComponents.IObject,
y: IJsonComponents.IObject,
): boolean {
if (x.nullable === true && true === y.nullable) return true;
return Object.keys(x).some((xk) =>
Object.keys(y).some((yk) => xk === yk),
);
}
}
16 changes: 16 additions & 0 deletions test/issues/202.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import TSON from "../../src";

type AnyTypeTry = { a: string };

const validation: TSON.IValidation = TSON.validateEquals<AnyTypeTry>({
a: "something",
b: "more",
c: "and",
d: "more",
});

console.log(
validation.errors
.filter((err) => err.expected === "undefined")
.map((err) => err.path),
);

0 comments on commit 4d4a68f

Please sign in to comment.