typia
Version:
Superfast runtime validators with only one line
131 lines (120 loc) • 4.13 kB
text/typescript
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],
);
}