UNPKG

typia

Version:

Superfast runtime validators with only one line

108 lines (99 loc) 3.33 kB
import ts from "typescript"; import { ExpressionFactory } from "../../factories/ExpressionFactory"; import { MetadataAtomic } from "../../schemas/metadata/MetadataAtomic"; import { IProject } from "../../transformers/IProject"; import { ICheckEntry } from "../helpers/ICheckEntry"; import { OptionPredicator } from "../helpers/OptionPredicator"; /** * @internal */ export const check_number = (project: IProject, numeric: boolean) => (atomic: MetadataAtomic) => (input: ts.Expression): ICheckEntry => { const base = ts.factory.createStrictEquality( ts.factory.createStringLiteral("number"), ts.factory.createTypeOfExpression(input), ); const addition: ts.Expression | null = numeric === true ? OptionPredicator.finite(project.options) ? ts.factory.createCallExpression( ts.factory.createIdentifier("Number.isFinite"), undefined, [input], ) : OptionPredicator.numeric(project.options) ? ts.factory.createLogicalNot( ts.factory.createCallExpression( ts.factory.createIdentifier("Number.isNaN"), undefined, [input], ), ) : null : null; const conditions: ICheckEntry.ICondition[][] = check_numeric_type_tags(project)(atomic)(addition)(input); return { expected: atomic.getName(), expression: addition !== null && conditions.length === 0 ? ts.factory.createLogicalAnd(base, addition) : base, conditions, }; }; /** * @internal */ const check_numeric_type_tags = (project: IProject) => (atomic: MetadataAtomic) => (addition: ts.Expression | null) => (input: ts.Expression): ICheckEntry.ICondition[][] => atomic.tags .map((row) => row.filter((tag) => !!tag.validate)) .filter((row) => !!row.length) .map((row) => [ ...(addition === null ? [] : row.some( (tag) => tag.kind === "type" && (tag.value === "int32" || tag.value === "uint32" || tag.value === "int64" || tag.value === "uint64" || tag.value === "float"), ) || row.some( (tag) => tag.kind === "multipleOf" && typeof tag.value === "number", ) || (row.some( (tag) => (tag.kind === "minimum" || tag.kind === "exclusiveMinimum") && typeof tag.value === "number", ) && row.some( (tag) => (tag.kind === "maximum" || tag.kind === "exclusiveMaximum") && typeof tag.value === "number", )) ? [] : [ { expected: "number", expression: addition!, }, ]), ...row.map((tag) => ({ expected: `number & ${tag.name}`, expression: ( tag.predicate ?? ExpressionFactory.transpile(project.context)(tag.validate!) )(input), })), ]);