UNPKG

typia

Version:

Superfast runtime validators with only one line

131 lines (120 loc) 4.13 kB
import ts from "typescript"; import { IdentifierFactory } from "../../factories/IdentifierFactory"; import { StatementFactory } from "../../factories/StatementFactory"; import { TypeFactory } from "../../factories/TypeFactory"; import { Escaper } from "../../utils/Escaper"; import { metadata_to_pattern } from "../internal/metadata_to_pattern"; import { IExpressionEntry } from "./IExpressionEntry"; export namespace CloneJoiner { export const object = ( input: ts.Expression, entries: IExpressionEntry<ts.Expression>[], ): ts.ConciseBody => { if (entries.length === 0) return ts.factory.createIdentifier("{}"); const regular = entries.filter((e) => e.key.isSoleLiteral()); const dynamic = entries.filter((e) => !e.key.isSoleLiteral()); const literal = ts.factory.createObjectLiteralExpression( regular.map((entry) => { const str: string = entry.key.getSoleLiteral()!; return ts.factory.createPropertyAssignment( Escaper.variable(str) ? str : ts.factory.createStringLiteral(str), entry.expression, ); }), true, ); if (dynamic.length === 0) return literal; const key = ts.factory.createIdentifier("key"); const output = ts.factory.createIdentifier("output"); const statements: ts.Statement[] = []; if (regular.length !== 0) statements.push( ts.factory.createIfStatement( ts.factory.createCallExpression( IdentifierFactory.access( ts.factory.createArrayLiteralExpression( regular.map((r) => ts.factory.createStringLiteral(r.key.getSoleLiteral()!), ), ), )("some"), undefined, [ ts.factory.createArrowFunction( undefined, undefined, [IdentifierFactory.parameter("regular")], undefined, undefined, ts.factory.createStrictEquality( ts.factory.createIdentifier("regular"), ts.factory.createIdentifier("key"), ), ), ], ), ts.factory.createContinueStatement(), ), ); statements.push( ...dynamic.map((entry) => ts.factory.createIfStatement( ts.factory.createCallExpression( ts.factory.createIdentifier( `RegExp(/${metadata_to_pattern(true)(entry.key)}/).test`, ), undefined, [key], ), ts.factory.createBlock([ ts.factory.createExpressionStatement( ts.factory.createBinaryExpression( ts.factory.createElementAccessExpression(output, key), ts.factory.createToken(ts.SyntaxKind.EqualsToken), entry.expression, ), ), ts.factory.createContinueStatement(), ]), ), ), ); return ts.factory.createBlock([ StatementFactory.constant( "output", ts.factory.createAsExpression(literal, TypeFactory.keyword("any")), ), ts.factory.createForOfStatement( undefined, StatementFactory.entry("key")("value"), ts.factory.createCallExpression( ts.factory.createIdentifier("Object.entries"), undefined, [input], ), ts.factory.createBlock(statements), ), ts.factory.createReturnStatement(output), ]); }; export const tuple = ( children: ts.Expression[], rest: ts.Expression | null, ): ts.Expression => { return ts.factory.createAsExpression( ts.factory.createArrayLiteralExpression( rest === null ? children : [...children, ts.factory.createSpreadElement(rest)], true, ), TypeFactory.keyword("any"), ); }; export const array = (input: ts.Expression, arrow: ts.Expression) => ts.factory.createCallExpression( ts.factory.createPropertyAccessExpression(input, "map"), undefined, [arrow], ); }