From bb398ba81600c883593819acf1acdfede99a59ce Mon Sep 17 00:00:00 2001 From: Jeongho Nam Date: Mon, 5 Aug 2024 07:08:39 +0900 Subject: [PATCH] Optimize `random()` and `clone()` functions. --- benchmark/package.json | 2 +- debug/package.json | 2 +- debug/src/clone.ts | 18 ++ errors/package.json | 2 +- package.json | 2 +- packages/typescript-json/package.json | 4 +- src/programmers/AssertProgrammer.ts | 1 - src/programmers/CheckerProgrammer.ts | 2 +- src/programmers/FeatureProgrammer.ts | 2 +- src/programmers/IsProgrammer.ts | 2 +- src/programmers/RandomProgrammer.ts | 189 +++++++++++------- src/programmers/ValidateProgrammer.ts | 2 +- src/programmers/json/JsonIsParseProgrammer.ts | 2 +- .../json/JsonIsStringifyProgrammer.ts | 2 +- .../json/JsonStringifyProgrammer.ts | 5 +- .../json/JsonValidateParseProgrammer.ts | 2 +- .../json/JsonValidateStringifyProgrammer.ts | 2 +- src/programmers/misc/MiscCloneProgrammer.ts | 68 ++++--- src/programmers/misc/MiscIsCloneProgrammer.ts | 2 +- src/programmers/misc/MiscIsPruneProgrammer.ts | 2 +- src/programmers/misc/MiscPruneProgrammer.ts | 2 +- .../misc/MiscValidateCloneProgrammer.ts | 2 +- .../misc/MiscValidatePruneProgrammer.ts | 2 +- .../notations/NotationGeneralProgrammer.ts | 46 ++++- .../NotationValidateGeneralProgrammer.ts | 2 +- test-esm/package.json | 2 +- test/package.json | 2 +- website/package.json | 2 +- 28 files changed, 235 insertions(+), 138 deletions(-) create mode 100644 debug/src/clone.ts diff --git a/benchmark/package.json b/benchmark/package.json index bbd4344a39..57596d88be 100644 --- a/benchmark/package.json +++ b/benchmark/package.json @@ -72,6 +72,6 @@ "suppress-warnings": "^1.0.2", "tstl": "^3.0.0", "uuid": "^9.0.1", - "typia": "../typia-6.7.0.tgz" + "typia": "../typia-6.7.1.tgz" } } \ No newline at end of file diff --git a/debug/package.json b/debug/package.json index 3ff457f542..bc7942ed9c 100644 --- a/debug/package.json +++ b/debug/package.json @@ -17,7 +17,7 @@ }, "dependencies": { "tstl": "^3.0.0", - "typia": "../typia-6.7.0-dev.20240803-4.tgz", + "typia": "../typia-6.7.1-dev.20240805.tgz", "uuid": "^10.0.0" } } \ No newline at end of file diff --git a/debug/src/clone.ts b/debug/src/clone.ts new file mode 100644 index 0000000000..557c13b162 --- /dev/null +++ b/debug/src/clone.ts @@ -0,0 +1,18 @@ +import typia from "typia"; + +export type ConstantAtomicUnion = ConstantAtomicUnion.Union[]; +export namespace ConstantAtomicUnion { + export type Union = false | 1 | 2 | "three" | "four" | { key: "key" }; +} +typia.misc.createClone(); + +// export type ConstantAtomicUnion = ConstantAtomicUnion.Union[]; +// export namespace ConstantAtomicUnion { +// export type Union = +// | false +// | 1 +// | 2 +// | "three" +// | "four" +// | { key: "key" }; +// } diff --git a/errors/package.json b/errors/package.json index d971f1f3b6..996a24589f 100644 --- a/errors/package.json +++ b/errors/package.json @@ -32,6 +32,6 @@ "typescript": "^5.3.2" }, "dependencies": { - "typia": "../typia-6.7.0.tgz" + "typia": "../typia-6.7.1.tgz" } } \ No newline at end of file diff --git a/package.json b/package.json index 6a6f6f06d9..b1de00886a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "typia", - "version": "6.7.0", + "version": "6.7.1", "description": "Superfast runtime validators with only one line", "main": "lib/index.js", "typings": "lib/index.d.ts", diff --git a/packages/typescript-json/package.json b/packages/typescript-json/package.json index 9cf010e37d..5bc1b8b240 100644 --- a/packages/typescript-json/package.json +++ b/packages/typescript-json/package.json @@ -1,6 +1,6 @@ { "name": "typescript-json", - "version": "6.7.0", + "version": "6.7.1", "description": "Superfast runtime validators with only one line", "main": "lib/index.js", "typings": "lib/index.d.ts", @@ -63,7 +63,7 @@ }, "homepage": "https://typia.io", "dependencies": { - "typia": "6.7.0" + "typia": "6.7.1" }, "peerDependencies": { "typescript": ">=4.8.0 <5.6.0" diff --git a/src/programmers/AssertProgrammer.ts b/src/programmers/AssertProgrammer.ts index ceca972a38..0c32e87a87 100644 --- a/src/programmers/AssertProgrammer.ts +++ b/src/programmers/AssertProgrammer.ts @@ -22,7 +22,6 @@ export namespace AssertProgrammer { type: ts.Type; name: string | undefined; init: ts.Expression | undefined; - inline?: boolean; }): FeatureProgrammer.IDecomposed => { const is: FeatureProgrammer.IDecomposed = IsProgrammer.decompose(props); const composed: FeatureProgrammer.IComposed = CheckerProgrammer.compose({ diff --git a/src/programmers/CheckerProgrammer.ts b/src/programmers/CheckerProgrammer.ts index c841badeab..b26016e148 100644 --- a/src/programmers/CheckerProgrammer.ts +++ b/src/programmers/CheckerProgrammer.ts @@ -102,7 +102,7 @@ export namespace CheckerProgrammer { config: IConfig; importer: FunctionImporter; type: ts.Type; - name?: string; + name: string | undefined; }) => FeatureProgrammer.compose({ ...props, diff --git a/src/programmers/FeatureProgrammer.ts b/src/programmers/FeatureProgrammer.ts index aee02c369f..a840d1fb65 100644 --- a/src/programmers/FeatureProgrammer.ts +++ b/src/programmers/FeatureProgrammer.ts @@ -216,7 +216,7 @@ export namespace FeatureProgrammer { config: IConfig; importer: FunctionImporter; type: ts.Type; - name?: string; + name: string | undefined; }): IComposed => { const [collection, meta] = props.config.initializer(props.project)( props.importer, diff --git a/src/programmers/IsProgrammer.ts b/src/programmers/IsProgrammer.ts index c4a9debdc4..ec8c3a5a9a 100644 --- a/src/programmers/IsProgrammer.ts +++ b/src/programmers/IsProgrammer.ts @@ -101,7 +101,7 @@ export namespace IsProgrammer { importer: FunctionImporter; equals: boolean; type: ts.Type; - name?: string; + name: string | undefined; }): FeatureProgrammer.IDecomposed => { // CONFIGURATION const config: CheckerProgrammer.IConfig = { diff --git a/src/programmers/RandomProgrammer.ts b/src/programmers/RandomProgrammer.ts index 631bd91600..7e28be4ea1 100644 --- a/src/programmers/RandomProgrammer.ts +++ b/src/programmers/RandomProgrammer.ts @@ -23,91 +23,126 @@ import { TransformerError } from "../transformers/TransformerError"; import { Escaper } from "../utils/Escaper"; import { Format } from "../tags"; +import { FeatureProgrammer } from "./FeatureProgrammer"; import { FunctionImporter } from "./helpers/FunctionImporter"; import { RandomJoiner } from "./helpers/RandomJoiner"; import { RandomRanger } from "./helpers/RandomRanger"; import { random_custom } from "./internal/random_custom"; export namespace RandomProgrammer { - export const write = - (project: IProject) => - (modulo: ts.LeftHandSideExpression) => - (init?: ts.Expression) => { - const importer: FunctionImporter = new FunctionImporter(modulo.getText()); - return (type: ts.Type, name?: string) => { - // INITIALIZE METADATA - const collection: MetadataCollection = new MetadataCollection(); - const result = MetadataFactory.analyze( - project.checker, - project.context, - )({ - escape: false, - constant: true, - absorb: true, - validate: (meta) => { - const output: string[] = []; - if (meta.natives.some((n) => n === "WeakSet")) - output.push(`WeakSet is not supported.`); - else if (meta.natives.some((n) => n === "WeakMap")) - output.push(`WeakMap is not supported.`); - return output; - }, - })(collection)(type); - if (result.success === false) - throw TransformerError.from(`typia.${importer.method}`)( - result.errors, - ); - - // GENERATE FUNCTION - const functions = { - objects: write_object_functions(importer)(collection), - arrays: write_array_functions(importer)(collection), - tuples: write_tuple_functions(importer)(collection), - }; - - const output: ts.Expression = decode(importer)({ - function: false, - recursive: false, - })(result.data); + export const decompose = (props: { + project: IProject; + importer: FunctionImporter; + type: ts.Type; + name: string | undefined; + init: ts.Expression | undefined; + }): FeatureProgrammer.IDecomposed => { + const collection: MetadataCollection = new MetadataCollection(); + const result = MetadataFactory.analyze( + props.project.checker, + props.project.context, + )({ + escape: false, + constant: true, + absorb: true, + validate: (meta) => { + const output: string[] = []; + if (meta.natives.some((n) => n === "WeakSet")) + output.push(`WeakSet is not supported.`); + else if (meta.natives.some((n) => n === "WeakMap")) + output.push(`WeakMap is not supported.`); + return output; + }, + })(collection)(props.type); + if (result.success === false) + throw TransformerError.from(`typia.${props.importer.method}`)( + result.errors, + ); - return ts.factory.createArrowFunction( - undefined, - undefined, - [ - IdentifierFactory.parameter( - "generator", - ts.factory.createTypeReferenceNode( - "Partial", - ), - init ?? ts.factory.createToken(ts.SyntaxKind.QuestionToken), - ), - ], - ts.factory.createImportTypeNode( - ts.factory.createLiteralTypeNode( - ts.factory.createStringLiteral("typia"), + // GENERATE FUNCTION + const functions: Record = Object.fromEntries([ + ...write_object_functions(props.importer)(collection).map((v, i) => [ + Prefix.object(i), + v, + ]), + ...write_array_functions(props.importer)(collection).map((v, i) => [ + Prefix.array(i), + v, + ]), + ...write_tuple_functions(props.importer)(collection).map((v, i) => [ + Prefix.tuple(i), + v, + ]), + ]); + const arrow: ts.ArrowFunction = ts.factory.createArrowFunction( + undefined, + undefined, + [ + IdentifierFactory.parameter( + "generator", + ts.factory.createTypeReferenceNode("Partial"), + props.init ?? ts.factory.createToken(ts.SyntaxKind.QuestionToken), + ), + ], + ts.factory.createImportTypeNode( + ts.factory.createLiteralTypeNode( + ts.factory.createStringLiteral("typia"), + ), + undefined, + ts.factory.createIdentifier("Resolved"), + [ + ts.factory.createTypeReferenceNode( + props.name ?? + TypeFactory.getFullName(props.project.checker)(props.type), + ), + ], + false, + ), + undefined, + ts.factory.createBlock( + [ + ts.factory.createExpressionStatement( + ts.factory.createBinaryExpression( + ts.factory.createIdentifier("_generator"), + ts.SyntaxKind.EqualsToken, + ts.factory.createIdentifier("generator"), ), - undefined, - ts.factory.createIdentifier("Resolved"), - [ - ts.factory.createTypeReferenceNode( - name ?? TypeFactory.getFullName(project.checker)(type), - ), - ], - false, ), - undefined, - ts.factory.createBlock( - [ - ...importer.declare(modulo), - ...functions.objects, - ...functions.arrays, - ...functions.tuples, - ts.factory.createReturnStatement(output), - ], - true, + ts.factory.createReturnStatement( + decode(props.importer)({ + function: false, + recursive: false, + })(result.data), ), - ); - }; + ], + true, + ), + ); + return { + functions, + statements: [StatementFactory.mut("_generator")], + arrow, + }; + }; + + export const write = + (project: IProject) => + (modulo: ts.LeftHandSideExpression) => + (init?: ts.Expression) => + (type: ts.Type, name?: string) => { + const importer: FunctionImporter = new FunctionImporter(modulo.getText()); + const result: FeatureProgrammer.IDecomposed = decompose({ + project, + importer, + type, + name, + init, + }); + return FeatureProgrammer.writeDecomposed({ + modulo, + importer, + result, + }); }; const write_object_functions = @@ -892,12 +927,12 @@ const COALESCE = (importer: FunctionImporter) => (name: string) => ExpressionFactory.coalesce( Escaper.variable(name) ? ts.factory.createPropertyAccessChain( - ts.factory.createIdentifier("generator"), + ts.factory.createIdentifier("_generator"), ts.factory.createToken(ts.SyntaxKind.QuestionDotToken), ts.factory.createIdentifier(name), ) : ts.factory.createElementAccessChain( - ts.factory.createIdentifier("generator"), + ts.factory.createIdentifier("_generator"), ts.factory.createToken(ts.SyntaxKind.QuestionDotToken), ts.factory.createStringLiteral(name), ), diff --git a/src/programmers/ValidateProgrammer.ts b/src/programmers/ValidateProgrammer.ts index 2b8971b16f..62b10c76e4 100644 --- a/src/programmers/ValidateProgrammer.ts +++ b/src/programmers/ValidateProgrammer.ts @@ -22,7 +22,7 @@ export namespace ValidateProgrammer { importer: FunctionImporter; equals: boolean; type: ts.Type; - name?: string; + name: string | undefined; }): FeatureProgrammer.IDecomposed => { const is: FeatureProgrammer.IDecomposed = IsProgrammer.decompose(props); const composed: FeatureProgrammer.IComposed = CheckerProgrammer.compose({ diff --git a/src/programmers/json/JsonIsParseProgrammer.ts b/src/programmers/json/JsonIsParseProgrammer.ts index b61c4a3c06..f33705a4b3 100644 --- a/src/programmers/json/JsonIsParseProgrammer.ts +++ b/src/programmers/json/JsonIsParseProgrammer.ts @@ -15,7 +15,7 @@ export namespace JsonIsParseProgrammer { project: IProject; importer: FunctionImporter; type: ts.Type; - name?: string; + name: string | undefined; }): FeatureProgrammer.IDecomposed => { const is: FeatureProgrammer.IDecomposed = IsProgrammer.decompose({ ...props, diff --git a/src/programmers/json/JsonIsStringifyProgrammer.ts b/src/programmers/json/JsonIsStringifyProgrammer.ts index 27a67c8d37..f0aa6845e0 100644 --- a/src/programmers/json/JsonIsStringifyProgrammer.ts +++ b/src/programmers/json/JsonIsStringifyProgrammer.ts @@ -16,7 +16,7 @@ export namespace JsonIsStringifyProgrammer { project: IProject; importer: FunctionImporter; type: ts.Type; - name?: string; + name: string | undefined; }): FeatureProgrammer.IDecomposed => { const is: FeatureProgrammer.IDecomposed = IsProgrammer.decompose({ ...props, diff --git a/src/programmers/json/JsonStringifyProgrammer.ts b/src/programmers/json/JsonStringifyProgrammer.ts index 55a79aacdb..1305a89d2e 100644 --- a/src/programmers/json/JsonStringifyProgrammer.ts +++ b/src/programmers/json/JsonStringifyProgrammer.ts @@ -42,7 +42,7 @@ export namespace JsonStringifyProgrammer { project: IProject; importer: FunctionImporter; type: ts.Type; - name?: string; + name: string | undefined; }): FeatureProgrammer.IDecomposed => { const config: FeatureProgrammer.IConfig = configure(props.project)( props.importer, @@ -852,8 +852,7 @@ export namespace JsonStringifyProgrammer { initializer, decoder: () => decode(project)(config)(importer), objector: { - checker: () => (input, meta, explore) => - IsProgrammer.decode(project)(importer)(input, meta, explore), + checker: () => IsProgrammer.decode(project)(importer), decoder: () => decode_object(importer), joiner: StringifyJoiner.object(importer), unionizer: decode_union_object( diff --git a/src/programmers/json/JsonValidateParseProgrammer.ts b/src/programmers/json/JsonValidateParseProgrammer.ts index db76397ec3..646e62d587 100644 --- a/src/programmers/json/JsonValidateParseProgrammer.ts +++ b/src/programmers/json/JsonValidateParseProgrammer.ts @@ -16,7 +16,7 @@ export namespace JsonValidateParseProgrammer { modulo: ts.LeftHandSideExpression; importer: FunctionImporter; type: ts.Type; - name?: string; + name: string | undefined; }): FeatureProgrammer.IDecomposed => { const validate: FeatureProgrammer.IDecomposed = ValidateProgrammer.decompose({ diff --git a/src/programmers/json/JsonValidateStringifyProgrammer.ts b/src/programmers/json/JsonValidateStringifyProgrammer.ts index 9fbc0504eb..773f14dbac 100644 --- a/src/programmers/json/JsonValidateStringifyProgrammer.ts +++ b/src/programmers/json/JsonValidateStringifyProgrammer.ts @@ -17,7 +17,7 @@ export namespace JsonValidateStringifyProgrammer { modulo: ts.LeftHandSideExpression; importer: FunctionImporter; type: ts.Type; - name?: string; + name: string | undefined; }): FeatureProgrammer.IDecomposed => { const validate: FeatureProgrammer.IDecomposed = ValidateProgrammer.decompose({ diff --git a/src/programmers/misc/MiscCloneProgrammer.ts b/src/programmers/misc/MiscCloneProgrammer.ts index 609ff3e2ae..c2bf09052e 100644 --- a/src/programmers/misc/MiscCloneProgrammer.ts +++ b/src/programmers/misc/MiscCloneProgrammer.ts @@ -30,7 +30,7 @@ export namespace MiscCloneProgrammer { project: IProject; importer: FunctionImporter; type: ts.Type; - name?: string; + name: string | undefined; }): FeatureProgrammer.IDecomposed => { const config = configure(props.project)(props.importer); if (props.validated === false) @@ -272,16 +272,31 @@ export namespace MiscCloneProgrammer { }); // COMPOSITION - let last: ts.Expression = input; - for (const u of unions.reverse()) - last = ts.factory.createConditionalExpression( - u.is(), - undefined, - u.value(), - undefined, - last, - ); - return ts.factory.createAsExpression(last, TypeFactory.keyword("any")); + if (unions.length === 0) return input; + else if (unions.length === 1 && meta.size() === 1) { + const value: ts.Expression = + (meta.nullable || meta.isRequired() === false) && is_instance(meta) + ? ts.factory.createConditionalExpression( + input, + undefined, + unions[0]!.value(), + undefined, + input, + ) + : unions[0]!.value(); + return ts.factory.createAsExpression(value, TypeFactory.keyword("any")); + } else { + let last: ts.Expression = input; + for (const u of unions.reverse()) + last = ts.factory.createConditionalExpression( + u.is(), + undefined, + u.value(), + undefined, + last, + ); + return ts.factory.createAsExpression(last, TypeFactory.keyword("any")); + } }; const decode_object = (importer: FunctionImporter) => @@ -566,18 +581,16 @@ export namespace MiscCloneProgrammer { input: ts.Expression, meta: Metadata, explore: FeatureProgrammer.IExplore, - ) => { - if (meta.objects.length === 1) - return decode_object(importer)(input, meta.objects[0]!, explore); - - return ts.factory.createCallExpression( - ts.factory.createIdentifier( - importer.useLocal(`${PREFIX}u${meta.union_index!}`), - ), - undefined, - FeatureProgrammer.argumentsArray(config)(explore)(input), - ); - }; + ) => + meta.objects.length === 1 + ? decode_object(importer)(input, meta.objects[0]!, explore) + : ts.factory.createCallExpression( + ts.factory.createIdentifier( + importer.useLocal(`${PREFIX}u${meta.union_index!}`), + ), + undefined, + FeatureProgrammer.argumentsArray(config)(explore)(input), + ); const explore_arrays = (project: IProject) => @@ -756,4 +769,13 @@ export namespace MiscCloneProgrammer { ], ), ); + + const is_instance = (meta: Metadata): boolean => + !!meta.objects.length || + !!meta.arrays.length || + !!meta.tuples.length || + !!meta.sets.length || + !!meta.maps.length || + !!meta.natives.length || + (meta.rest !== null && is_instance(meta.rest)); } diff --git a/src/programmers/misc/MiscIsCloneProgrammer.ts b/src/programmers/misc/MiscIsCloneProgrammer.ts index e06a59500e..50f4f9a231 100644 --- a/src/programmers/misc/MiscIsCloneProgrammer.ts +++ b/src/programmers/misc/MiscIsCloneProgrammer.ts @@ -16,7 +16,7 @@ export namespace MiscIsCloneProgrammer { project: IProject; importer: FunctionImporter; type: ts.Type; - name?: string; + name: string | undefined; }): FeatureProgrammer.IDecomposed => { const is: FeatureProgrammer.IDecomposed = IsProgrammer.decompose({ ...props, diff --git a/src/programmers/misc/MiscIsPruneProgrammer.ts b/src/programmers/misc/MiscIsPruneProgrammer.ts index 621360b593..67e7c91752 100644 --- a/src/programmers/misc/MiscIsPruneProgrammer.ts +++ b/src/programmers/misc/MiscIsPruneProgrammer.ts @@ -16,7 +16,7 @@ export namespace MiscIsPruneProgrammer { project: IProject; importer: FunctionImporter; type: ts.Type; - name?: string; + name: string | undefined; }): FeatureProgrammer.IDecomposed => { const is: FeatureProgrammer.IDecomposed = IsProgrammer.decompose({ ...props, diff --git a/src/programmers/misc/MiscPruneProgrammer.ts b/src/programmers/misc/MiscPruneProgrammer.ts index e1a9854fc0..fc4b59469d 100644 --- a/src/programmers/misc/MiscPruneProgrammer.ts +++ b/src/programmers/misc/MiscPruneProgrammer.ts @@ -30,7 +30,7 @@ export namespace MiscPruneProgrammer { project: IProject; importer: FunctionImporter; type: ts.Type; - name?: string; + name: string | undefined; }): FeatureProgrammer.IDecomposed => { const config = configure(props.project)(props.importer); if (props.validated === false) diff --git a/src/programmers/misc/MiscValidateCloneProgrammer.ts b/src/programmers/misc/MiscValidateCloneProgrammer.ts index e3384f15d7..daf630b69d 100644 --- a/src/programmers/misc/MiscValidateCloneProgrammer.ts +++ b/src/programmers/misc/MiscValidateCloneProgrammer.ts @@ -17,7 +17,7 @@ export namespace MiscValidateCloneProgrammer { modulo: ts.LeftHandSideExpression; importer: FunctionImporter; type: ts.Type; - name?: string; + name: string | undefined; }): FeatureProgrammer.IDecomposed => { const validate = ValidateProgrammer.decompose({ ...props, diff --git a/src/programmers/misc/MiscValidatePruneProgrammer.ts b/src/programmers/misc/MiscValidatePruneProgrammer.ts index 967b2ebb8c..d3dc546ee7 100644 --- a/src/programmers/misc/MiscValidatePruneProgrammer.ts +++ b/src/programmers/misc/MiscValidatePruneProgrammer.ts @@ -17,7 +17,7 @@ export namespace MiscValidatePruneProgrammer { modulo: ts.LeftHandSideExpression; importer: FunctionImporter; type: ts.Type; - name?: string; + name: string | undefined; }): FeatureProgrammer.IDecomposed => { const validate: FeatureProgrammer.IDecomposed = ValidateProgrammer.decompose({ diff --git a/src/programmers/notations/NotationGeneralProgrammer.ts b/src/programmers/notations/NotationGeneralProgrammer.ts index a5127e5122..c75b12b218 100644 --- a/src/programmers/notations/NotationGeneralProgrammer.ts +++ b/src/programmers/notations/NotationGeneralProgrammer.ts @@ -37,7 +37,7 @@ export namespace NotationGeneralProgrammer { project: IProject; importer: FunctionImporter; type: ts.Type; - name?: string; + name: string | undefined; }): FeatureProgrammer.IDecomposed => { const config = configure(props.rename)(props.project)(props.importer); if (props.validated === false) @@ -283,16 +283,31 @@ export namespace NotationGeneralProgrammer { }); // COMPOSITION - let last: ts.Expression = input; - for (const u of unions.reverse()) - last = ts.factory.createConditionalExpression( - u.is(), - undefined, - u.value(), - undefined, - last, - ); - return ts.factory.createAsExpression(last, TypeFactory.keyword("any")); + if (unions.length === 0) return input; + else if (unions.length === 1 && meta.size() === 1) { + const value: ts.Expression = + (meta.nullable || meta.isRequired() === false) && is_instance(meta) + ? ts.factory.createConditionalExpression( + input, + undefined, + unions[0]!.value(), + undefined, + input, + ) + : unions[0]!.value(); + return ts.factory.createAsExpression(value, TypeFactory.keyword("any")); + } else { + let last: ts.Expression = input; + for (const u of unions.reverse()) + last = ts.factory.createConditionalExpression( + u.is(), + undefined, + u.value(), + undefined, + last, + ); + return ts.factory.createAsExpression(last, TypeFactory.keyword("any")); + } }; const decode_object = (importer: FunctionImporter) => @@ -682,4 +697,13 @@ export namespace NotationGeneralProgrammer { ], ), ); + + const is_instance = (meta: Metadata): boolean => + !!meta.objects.length || + !!meta.arrays.length || + !!meta.tuples.length || + !!meta.sets.length || + !!meta.maps.length || + !!meta.natives.length || + (meta.rest !== null && is_instance(meta.rest)); } diff --git a/src/programmers/notations/NotationValidateGeneralProgrammer.ts b/src/programmers/notations/NotationValidateGeneralProgrammer.ts index 8cb4544c7f..552098bde4 100644 --- a/src/programmers/notations/NotationValidateGeneralProgrammer.ts +++ b/src/programmers/notations/NotationValidateGeneralProgrammer.ts @@ -18,7 +18,7 @@ export namespace NotationValidateGeneralProgrammer { modulo: ts.LeftHandSideExpression; importer: FunctionImporter; type: ts.Type; - name?: string; + name: string | undefined; }): FeatureProgrammer.IDecomposed => { const validate = ValidateProgrammer.decompose({ ...props, diff --git a/test-esm/package.json b/test-esm/package.json index 1ae7cef4f2..2321480b11 100644 --- a/test-esm/package.json +++ b/test-esm/package.json @@ -36,6 +36,6 @@ "typescript": "^5.4.5" }, "dependencies": { - "typia": "../typia-6.7.0.tgz" + "typia": "../typia-6.7.1.tgz" } } \ No newline at end of file diff --git a/test/package.json b/test/package.json index 18b2926485..0f9f4f3dac 100644 --- a/test/package.json +++ b/test/package.json @@ -51,6 +51,6 @@ "suppress-warnings": "^1.0.2", "tstl": "^3.0.0", "uuid": "^9.0.1", - "typia": "../typia-6.7.0.tgz" + "typia": "../typia-6.7.1.tgz" } } \ No newline at end of file diff --git a/website/package.json b/website/package.json index c877bfb502..94cc07cdc9 100644 --- a/website/package.json +++ b/website/package.json @@ -38,7 +38,7 @@ "tgrid": "^1.0.3", "tstl": "^3.0.0", "typescript": "^5.5.4", - "typia": "^6.7.0" + "typia": "^6.7.1" }, "devDependencies": { "@trivago/prettier-plugin-sort-imports": "^4.3.0",