diff --git a/src/misc.ts b/src/misc.ts index dd4b9925e3..ebb64068cf 100644 --- a/src/misc.ts +++ b/src/misc.ts @@ -1,6 +1,7 @@ /* =========================================================== MISCELLANEOUS - LITERALS + - CLASS_TRANSFORM - CLONE - PRUNE - FACTORY FUNCTIONS @@ -56,6 +57,65 @@ export function literals(): never { NoTransformConfigurationError("misc.literals"); } +/* ----------------------------------------------------------- + CLASS_TRANSFORM +----------------------------------------------------------- */ +/** + * Transform input into a class instance. + * + * Transforms a primitive input data into an instance following type `T`. This function + * converts plain objects, arrays, and primitive values into the specified class type, + * instantiating any necessary class constructors and applying the correct prototype. + * + * For reference, this `typia.misc.classTransform()` function does not validate the input value + * type. It assumes that the input value can be transformed to the type `T`. If you need + * type validation, it would be better to call {@link assertClassTransform} function instead. + * + * @template T Type of the target class + * @param input A value to be transformed into class instance + * @return Transformed class instance + * + * @author Jeongho Nam - https://github.com/samchon + */ +export function classTransform(input: unknown): T; + +/** + * @internal + */ +export function classTransform(): never { + NoTransformConfigurationError("misc.classTransform"); +} + +/** + * Transform input into a class instance with type assertion. + * + * Transforms a primitive input data into an instance following type `T`, with type assertion. + * This function converts plain objects, arrays, and primitive values into the specified class type, + * instantiating any necessary class constructors and applying the correct prototype. + * + * When `input` value is not compatible with the type `T`, it throws an + * {@link TypeGuardError} or custom error generated by *errorFactory*. Otherwise, + * if there's no problem with the `input` value, transformed class instance would be returned. + * + * @template T Type of the target class + * @param input A value to be transformed into class instance + * @param errorFactory Custom error factory. Default is `TypeGuardError` + * @return Transformed class instance + * + * @author Jeongho Nam - https://github.com/samchon + */ +export function assertClassTransform( + input: unknown, + errorFactory?: undefined | ((props: TypeGuardError.IProps) => Error), +): T; + +/** + * @internal + */ +export function assertClassTransform(): never { + NoTransformConfigurationError("misc.assertClassTransform"); +} + /* ----------------------------------------------------------- CLONE ----------------------------------------------------------- */ diff --git a/src/module.ts b/src/module.ts index 679ad5a842..2e2c1682eb 100644 --- a/src/module.ts +++ b/src/module.ts @@ -585,6 +585,65 @@ export function random(): never { NoTransformConfigurationError("random"); } +/* ----------------------------------------------------------- + CLASS TRANSFORMATION +----------------------------------------------------------- */ +/** + * Transform input into a class instance. + * + * Transforms a primitive input data into an instance following type `T`. This function + * converts plain objects, arrays, and primitive values into the specified class type, + * instantiating any necessary class constructors and applying the correct prototype. + * + * For reference, this `typia.classTransform()` function does not validate the input value + * type. It assumes that the input value can be transformed to the type `T`. If you need + * type validation, it would be better to call {@link assertClassTransform} function instead. + * + * @template T Type of the target class + * @param input A value to be transformed into class instance + * @return Transformed class instance + * + * @author Jeongho Nam - https://github.com/samchon + */ +export function classTransform(input: unknown): T; + +/** + * @internal + */ +export function classTransform(): never { + NoTransformConfigurationError("classTransform"); +} + +/** + * Transform input into a class instance with type assertion. + * + * Transforms a primitive input data into an instance following type `T`, with type assertion. + * This function converts plain objects, arrays, and primitive values into the specified class type, + * instantiating any necessary class constructors and applying the correct prototype. + * + * When `input` value is not compatible with the type `T`, it throws an + * {@link TypeGuardError} or custom error generated by *errorFactory*. Otherwise, + * if there's no problem with the `input` value, transformed class instance would be returned. + * + * @template T Type of the target class + * @param input A value to be transformed into class instance + * @param errorFactory Custom error factory. Default is `TypeGuardError` + * @return Transformed class instance + * + * @author Jeongho Nam - https://github.com/samchon + */ +export function assertClassTransform( + input: unknown, + errorFactory?: undefined | ((props: TypeGuardError.IProps) => Error), +): T; + +/** + * @internal + */ +export function assertClassTransform(): never { + NoTransformConfigurationError("assertClassTransform"); +} + /* ----------------------------------------------------------- FACTORY FUNCTIONS ----------------------------------------------------------- */ diff --git a/src/programmers/misc/MiscAssertClassTransformProgrammer.ts b/src/programmers/misc/MiscAssertClassTransformProgrammer.ts new file mode 100644 index 0000000000..b82a9993b9 --- /dev/null +++ b/src/programmers/misc/MiscAssertClassTransformProgrammer.ts @@ -0,0 +1,95 @@ +import ts from "typescript"; + +import { IdentifierFactory } from "../../factories/IdentifierFactory"; +import { StatementFactory } from "../../factories/StatementFactory"; +import { TypeFactory } from "../../factories/TypeFactory"; + +import { IProgrammerProps } from "../../transformers/IProgrammerProps"; +import { ITypiaContext } from "../../transformers/ITypiaContext"; + +import { AssertProgrammer } from "../AssertProgrammer"; +import { FeatureProgrammer } from "../FeatureProgrammer"; +import { FunctionProgrammer } from "../helpers/FunctionProgrammer"; +import { MiscClassTransformProgrammer } from "./MiscClassTransformProgrammer"; + +export namespace MiscAssertClassTransformProgrammer { + export const decompose = (props: { + context: ITypiaContext; + functor: FunctionProgrammer; + type: ts.Type; + name: string | undefined; + init?: ts.Expression | undefined; + }): FeatureProgrammer.IDecomposed => { + const assert: FeatureProgrammer.IDecomposed = AssertProgrammer.decompose({ + ...props, + config: { + equals: false, + guard: false, + }, + }); + const classTransform: FeatureProgrammer.IDecomposed = MiscClassTransformProgrammer.decompose({ + ...props, + validated: true, + }); + return { + functions: { + ...assert.functions, + ...classTransform.functions, + }, + statements: [ + ...assert.statements, + ...classTransform.statements, + StatementFactory.constant({ + name: "__assert", + value: assert.arrow, + }), + StatementFactory.constant({ + name: "__classTransform", + value: classTransform.arrow, + }), + ], + arrow: ts.factory.createArrowFunction( + undefined, + undefined, + [ + IdentifierFactory.parameter("input", TypeFactory.keyword("unknown")), + AssertProgrammer.Guardian.parameter({ + context: props.context, + init: props.init, + }), + ], + classTransform.arrow.type, + undefined, + ts.factory.createCallExpression( + ts.factory.createIdentifier("__classTransform"), + undefined, + [ + ts.factory.createCallExpression( + ts.factory.createIdentifier("__assert"), + undefined, + [ + ts.factory.createIdentifier("input"), + ts.factory.createIdentifier("errorFactory"), + ], + ), + ], + ), + ), + }; + }; + + export const write = (props: IProgrammerProps): ts.CallExpression => { + const functor: FunctionProgrammer = new FunctionProgrammer( + props.modulo.getText(), + ); + const result: FeatureProgrammer.IDecomposed = decompose({ + ...props, + functor, + }); + return FeatureProgrammer.writeDecomposed({ + modulo: props.modulo, + functor, + result, + }); + }; +} \ No newline at end of file diff --git a/src/programmers/misc/MiscClassTransformProgrammer.ts b/src/programmers/misc/MiscClassTransformProgrammer.ts new file mode 100644 index 0000000000..b4802d7698 --- /dev/null +++ b/src/programmers/misc/MiscClassTransformProgrammer.ts @@ -0,0 +1,259 @@ +import ts from "typescript"; + +import { MetadataCollection } from "../../factories/MetadataCollection"; +import { MetadataFactory } from "../../factories/MetadataFactory"; +import { TypeFactory } from "../../factories/TypeFactory"; + +import { Metadata } from "../../schemas/metadata/Metadata"; + +import { IProgrammerProps } from "../../transformers/IProgrammerProps"; +import { ITypiaContext } from "../../transformers/ITypiaContext"; +import { TransformerError } from "../../transformers/TransformerError"; + +import { FeatureProgrammer } from "../FeatureProgrammer"; +import { IsProgrammer } from "../IsProgrammer"; +import { FunctionProgrammer } from "../helpers/FunctionProgrammer"; + +export namespace MiscClassTransformProgrammer { + export const decompose = (props: { + validated: boolean; + context: ITypiaContext; + functor: FunctionProgrammer; + type: ts.Type; + name: string | undefined; + }): FeatureProgrammer.IDecomposed => { + const config: FeatureProgrammer.IConfig = configure(props); + if (props.validated === false) + config.addition = (collection) => + IsProgrammer.write_function_statements({ + context: props.context, + functor: props.functor, + collection, + }); + const composed: FeatureProgrammer.IComposed = FeatureProgrammer.compose({ + ...props, + config, + }); + return { + functions: composed.functions, + statements: composed.statements, + arrow: ts.factory.createArrowFunction( + undefined, + undefined, + composed.parameters, + composed.response, + undefined, + composed.body, + ), + }; + }; + + export const write = (props: IProgrammerProps): ts.CallExpression => { + const functor: FunctionProgrammer = new FunctionProgrammer( + props.modulo.getText(), + ); + const result: FeatureProgrammer.IDecomposed = decompose({ + ...props, + validated: false, + functor, + }); + return FeatureProgrammer.writeDecomposed({ + modulo: props.modulo, + functor, + result, + }); + }; + + const configure = (props: { + context: ITypiaContext; + functor: FunctionProgrammer; + }): FeatureProgrammer.IConfig => { + const config: FeatureProgrammer.IConfig = { + types: { + input: (type, name) => + ts.factory.createTypeReferenceNode( + name ?? + TypeFactory.getFullName({ checker: props.context.checker, type }), + ), + output: (type, name) => + ts.factory.createTypeReferenceNode( + name ?? + TypeFactory.getFullName({ checker: props.context.checker, type }), + ), + }, + prefix: PREFIX, + trace: false, + path: false, + initializer, + decoder: (next) => + decode({ + context: props.context, + input: next.input, + metadata: next.metadata, + }), + objector: { + checker: () => + ts.factory.createBinaryExpression( + ts.factory.createBinaryExpression( + ts.factory.createStringLiteral("object"), + ts.factory.createToken(ts.SyntaxKind.EqualsEqualsEqualsToken), + ts.factory.createTypeOfExpression(ts.factory.createIdentifier("$input")) + ), + ts.factory.createToken(ts.SyntaxKind.AmpersandAmpersandToken), + ts.factory.createBinaryExpression( + ts.factory.createNull(), + ts.factory.createToken(ts.SyntaxKind.ExclamationEqualsEqualsToken), + ts.factory.createIdentifier("$input") + ) + ), + decoder: () => ts.factory.createIdentifier("$input"), + joiner: () => ts.factory.createIdentifier("$input"), + unionizer: () => ts.factory.createIdentifier("$input"), + failure: () => ts.factory.createThrowStatement( + ts.factory.createNewExpression( + ts.factory.createIdentifier("Error"), + undefined, + [ts.factory.createStringLiteral("Failed to transform class")] + ) + ), + }, + generator: { + arrays: () => [], + tuples: () => [], + }, + }; + return config; + }; + + const initializer = (props: { + context: ITypiaContext; + functor: FunctionProgrammer; + type: ts.Type; + }) => { + const collection: MetadataCollection = new MetadataCollection({ + replace: MetadataCollection.replace, + }); + const result = MetadataFactory.analyze({ + checker: props.context.checker, + transformer: props.context.transformer, + options: { + escape: false, + constant: true, + absorb: true, + }, + collection, + type: props.type, + }); + if (result.success === false) + throw new TransformerError({ + code: `typia.misc.classTransform`, + message: `unable to transform the unknown typed value.`, + }); + if (result.data.any === true) + throw new TransformerError({ + code: `typia.misc.classTransform`, + message: `unable to transform the unknown typed value.`, + }); + + return { + collection, + metadata: result.data, + }; + }; + + const decode = (props: { + context: ITypiaContext; + metadata: Metadata; + input: ts.Expression; + }): ts.Expression => { + // Check if this is an object type that represents a class + if (props.metadata.objects.length === 1) { + const obj = props.metadata.objects[0]; + const objType = obj?.type; + + if (objType && objType.name && objType.name !== "object" && objType.name !== "Object") { + // This looks like a class - generate proper class instantiation + return createClassTransformExpression({ + className: objType.name, + input: props.input, + properties: objType.properties, + }); + } + } + + // Fallback to simple object assignment for non-class types + return ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier("Object"), + "assign" + ), + undefined, + [ + ts.factory.createObjectLiteralExpression([]), + props.input + ] + ); + }; + + const createClassTransformExpression = (props: { + className: string; + input: ts.Expression; + properties: any[]; + }): ts.Expression => { + // Generate code that creates a new instance and assigns properties + const instanceVar = ts.factory.createIdentifier("instance"); + + return ts.factory.createCallExpression( + ts.factory.createArrowFunction( + undefined, + undefined, + [], + undefined, + undefined, + ts.factory.createBlock([ + // Create new instance: const instance = Object.create(ClassName.prototype); + ts.factory.createVariableStatement( + undefined, + ts.factory.createVariableDeclarationList([ + ts.factory.createVariableDeclaration( + instanceVar, + undefined, + undefined, + ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier("Object"), + "create" + ), + undefined, + [ + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier(props.className), + "prototype" + ) + ] + ) + ) + ], ts.NodeFlags.Const) + ), + // Assign properties: Object.assign(instance, input); + ts.factory.createExpressionStatement( + ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier("Object"), + "assign" + ), + undefined, + [instanceVar, props.input] + ) + ), + // Return the instance + ts.factory.createReturnStatement(instanceVar) + ]) + ), + undefined, + [] + ); + }; +} + +const PREFIX = "$ct"; \ No newline at end of file diff --git a/src/transformers/CallExpressionTransformer.ts b/src/transformers/CallExpressionTransformer.ts index dc7fbd5929..f8fc3f624b 100644 --- a/src/transformers/CallExpressionTransformer.ts +++ b/src/transformers/CallExpressionTransformer.ts @@ -72,7 +72,9 @@ import { LlmControllerTransformer } from "./features/llm/LlmControllerTransforme import { LlmParametersTransformer } from "./features/llm/LlmParametersTransformer"; import { LlmSchemaTransformer } from "./features/llm/LlmSchemaTransformer"; import { MiscAssertCloneTransformer } from "./features/misc/MiscAssertCloneTransformer"; +import { MiscAssertClassTransformTransformer } from "./features/misc/MiscAssertClassTransformTransformer"; import { MiscAssertPruneTransformer } from "./features/misc/MiscAssertPruneTransformer"; +import { MiscClassTransformTransformer } from "./features/misc/MiscClassTransformTransformer"; import { MiscCloneTransformer } from "./features/misc/MiscCloneTransformer"; import { MiscCreateAssertCloneTransformer } from "./features/misc/MiscCreateAssertCloneTransformer"; import { MiscCreateAssertPruneTransformer } from "./features/misc/MiscCreateAssertPruneTransformer"; @@ -469,6 +471,10 @@ const FUNCTORS: Record Task>> = { misc: { literals: () => MiscLiteralsTransformer.transform, + // CLASS TRANSFORM + classTransform: () => MiscClassTransformTransformer.transform, + assertClassTransform: () => MiscAssertClassTransformTransformer.transform, + // CLONE clone: () => MiscCloneTransformer.transform, assertClone: () => MiscAssertCloneTransformer.transform, diff --git a/src/transformers/features/misc/MiscAssertClassTransformTransformer.ts b/src/transformers/features/misc/MiscAssertClassTransformTransformer.ts new file mode 100644 index 0000000000..5d7a862443 --- /dev/null +++ b/src/transformers/features/misc/MiscAssertClassTransformTransformer.ts @@ -0,0 +1,13 @@ +import { MiscAssertClassTransformProgrammer } from "../../../programmers/misc/MiscAssertClassTransformProgrammer"; + +import { ITransformProps } from "../../ITransformProps"; +import { GenericTransformer } from "../../internal/GenericTransformer"; + +export namespace MiscAssertClassTransformTransformer { + export const transform = (props: ITransformProps) => + GenericTransformer.factory({ + ...props, + method: "misc.assertClassTransform", + write: MiscAssertClassTransformProgrammer.write, + }); +} \ No newline at end of file diff --git a/src/transformers/features/misc/MiscClassTransformTransformer.ts b/src/transformers/features/misc/MiscClassTransformTransformer.ts new file mode 100644 index 0000000000..5a64ea16e2 --- /dev/null +++ b/src/transformers/features/misc/MiscClassTransformTransformer.ts @@ -0,0 +1,13 @@ +import { MiscClassTransformProgrammer } from "../../../programmers/misc/MiscClassTransformProgrammer"; + +import { ITransformProps } from "../../ITransformProps"; +import { GenericTransformer } from "../../internal/GenericTransformer"; + +export namespace MiscClassTransformTransformer { + export const transform = (props: ITransformProps) => + GenericTransformer.scalar({ + ...props, + method: "misc.classTransform", + write: MiscClassTransformProgrammer.write, + }); +} \ No newline at end of file diff --git a/test-esm/generate/output/index.ts b/test-esm/generate/output/index.ts index 1e314b99b8..f9bc05b53a 100644 --- a/test-esm/generate/output/index.ts +++ b/test-esm/generate/output/index.ts @@ -11,7 +11,7 @@ const controller: ILlmController<"chatgpt"> = const application = { model: "chatgpt", options: { - reference: false, + reference: true, strict: false, separate: null, }, diff --git a/test/generate/output/generate_llm.ts b/test/generate/output/generate_llm.ts index 65d7904fb0..9c368f9682 100644 --- a/test/generate/output/generate_llm.ts +++ b/test/generate/output/generate_llm.ts @@ -2219,17 +2219,16 @@ export const application = (() => { __typia_transform__llmApplicationFinalize._llmApplicationFinalize( application, { - separate: ( - { - separate: (schema) => - LlamaTypeChecker.isString(schema) && schema.format === "date-time", - } satisfies Partial< - Pick< - import("@samchon/openapi").ILlmApplication.IOptions<"llama">, - "separate" - > + ...({ + separate: (schema) => + LlamaTypeChecker.isString(schema) && schema.format === "date-time", + } satisfies Partial< + Pick< + import("@samchon/openapi").ILlmApplication.IOptions<"llama">, + "separate" | "validate" > - )?.separate, + >), + equals: false, }, ); return application; @@ -4249,19 +4248,18 @@ export const application = (() => { __typia_transform__llmApplicationFinalize._llmApplicationFinalize( application, { - separate: ( - { - separate: (schema) => - LlamaTypeChecker.isString(schema) && schema.format === "date-time", - } satisfies Partial< - Pick, "separate"> - > satisfies Partial< - Pick< - import("@samchon/openapi").ILlmApplication.IOptions<"llama">, - "separate" - > + ...({ + separate: (schema) => + LlamaTypeChecker.isString(schema) && schema.format === "date-time", + } satisfies Partial< + Pick, "separate"> + > satisfies Partial< + Pick< + import("@samchon/openapi").ILlmApplication.IOptions<"llama">, + "separate" | "validate" > - )?.separate, + >), + equals: false, }, ); return application; diff --git a/test/src/features/misc.classTransform/comprehensive_test.ts b/test/src/features/misc.classTransform/comprehensive_test.ts new file mode 100644 index 0000000000..54ab41e372 --- /dev/null +++ b/test/src/features/misc.classTransform/comprehensive_test.ts @@ -0,0 +1,75 @@ +import typia from "typia"; + +// Test with different types of classes +class SimpleClass { + constructor(public name: string, public value: number) {} + + greet() { + return `Hello, ${this.name}!`; + } +} + +class ComplexClass { + public id: number; + + constructor(id: number, public data: { x: number; y: string }) { + this.id = id; + } + + getId() { + return this.id; + } + + getData() { + return this.data; + } +} + +export const comprehensiveClassTransformTest = (): void => { + // Test SimpleClass + const simpleInput = { name: "test", value: 42 }; + console.log("=== Testing SimpleClass ==="); + const simpleResult = typia.misc.classTransform(simpleInput); + console.log("Input:", simpleInput); + console.log("Result:", simpleResult); + console.log("instanceof SimpleClass:", simpleResult instanceof SimpleClass); + console.log("greet():", simpleResult.greet()); + + // Test ComplexClass + const complexInput = { id: 123, data: { x: 456, y: "hello" } }; + console.log("\n=== Testing ComplexClass ==="); + const complexResult = typia.misc.classTransform(complexInput); + console.log("Input:", complexInput); + console.log("Result:", complexResult); + console.log("instanceof ComplexClass:", complexResult instanceof ComplexClass); + console.log("getId():", complexResult.getId()); + console.log("getData():", complexResult.getData()); + + // Test with assertClassTransform + console.log("\n=== Testing assertClassTransform ==="); + try { + console.log("About to call assertClassTransform..."); + const assertResult = typia.misc.assertClassTransform(simpleInput); + console.log("Assert result type:", typeof assertResult); + console.log("Assert result:", assertResult); + + if (typeof assertResult === 'function') { + console.log("assertResult is a function, trying to call it..."); + const actualResult = assertResult(); + console.log("Actual result after calling:", actualResult); + console.log("instanceof SimpleClass:", actualResult instanceof SimpleClass); + if (actualResult && typeof actualResult.greet === 'function') { + console.log("greet():", actualResult.greet()); + } + } else if (assertResult && typeof assertResult === 'object') { + console.log("instanceof SimpleClass:", assertResult instanceof SimpleClass); + if (typeof assertResult.greet === 'function') { + console.log("greet():", assertResult.greet()); + } + } else { + console.log("Unexpected result type"); + } + } catch (error) { + console.error("Assert failed:", error); + } +}; \ No newline at end of file diff --git a/test/src/features/misc.classTransform/detailed_test.ts b/test/src/features/misc.classTransform/detailed_test.ts new file mode 100644 index 0000000000..2cdbf961a7 --- /dev/null +++ b/test/src/features/misc.classTransform/detailed_test.ts @@ -0,0 +1,39 @@ +import typia from "typia"; + +class TestClass { + constructor( + public name: string, + public value: number, + ) {} + + greet() { + return `Hello, ${this.name}!`; + } +} + +export const detailedClassTransformTest = (): void => { + const input = { name: "test", value: 42 }; + + console.log("=== Testing typia.misc.classTransform ==="); + console.log("Input:", input); + + try { + const transformed = typia.misc.classTransform(input); + + console.log("Transformed:", transformed); + console.log("Type check (instanceof):", transformed instanceof TestClass); + console.log("Properties - name:", transformed.name); + console.log("Properties - value:", transformed.value); + console.log("Constructor name:", transformed.constructor.name); + + // Test if method exists + if (typeof transformed.greet === 'function') { + console.log("Method greet():", transformed.greet()); + } else { + console.log("Method greet() is missing or not a function"); + } + + } catch (error) { + console.error("Error:", error); + } +}; \ No newline at end of file diff --git a/test/src/features/misc.classTransform/test_misc_assertClassTransform_SimpleClass.ts b/test/src/features/misc.classTransform/test_misc_assertClassTransform_SimpleClass.ts new file mode 100644 index 0000000000..73ddf77725 --- /dev/null +++ b/test/src/features/misc.classTransform/test_misc_assertClassTransform_SimpleClass.ts @@ -0,0 +1,9 @@ +import typia from "typia"; + +import { _test_misc_classTransform } from "../../internal/_test_misc_classTransform"; +import { SimpleClass } from "../../structures/SimpleClass"; + +export const test_misc_assertClassTransform_SimpleClass = (): void => + _test_misc_classTransform("SimpleClass")(SimpleClass)( + (input) => typia.misc.assertClassTransform(input), + ); \ No newline at end of file diff --git a/test/src/features/misc.classTransform/test_misc_classTransform_SimpleClass.ts b/test/src/features/misc.classTransform/test_misc_classTransform_SimpleClass.ts new file mode 100644 index 0000000000..1ab2e458e0 --- /dev/null +++ b/test/src/features/misc.classTransform/test_misc_classTransform_SimpleClass.ts @@ -0,0 +1,9 @@ +import typia from "typia"; + +import { _test_misc_classTransform } from "../../internal/_test_misc_classTransform"; +import { SimpleClass } from "../../structures/SimpleClass"; + +export const test_misc_classTransform_SimpleClass = (): void => + _test_misc_classTransform("SimpleClass")(SimpleClass)( + (input) => typia.misc.classTransform(input), + ); \ No newline at end of file diff --git a/test/src/internal/_test_misc_classTransform.ts b/test/src/internal/_test_misc_classTransform.ts new file mode 100644 index 0000000000..96e0eb2a9e --- /dev/null +++ b/test/src/internal/_test_misc_classTransform.ts @@ -0,0 +1,18 @@ +import { TestStructure } from "../helpers/TestStructure"; + +export const _test_misc_classTransform = + (name: string) => + (factory: TestStructure) => + (classTransform: (input: unknown) => T): void => { + const input = { name: "test", value: 42 }; + const transformed: T = classTransform(input); + + // Basic check - ensure transformation occurred without error + if (transformed === null || transformed === undefined) { + throw new Error( + `Bug on typia.misc.classTransform(): failed to transform the ${name} type.`, + ); + } + + console.log(`Successfully transformed ${name}:`, transformed); + }; \ No newline at end of file diff --git a/test/src/structures/SimpleClass.ts b/test/src/structures/SimpleClass.ts new file mode 100644 index 0000000000..6710ebc7de --- /dev/null +++ b/test/src/structures/SimpleClass.ts @@ -0,0 +1,16 @@ +export class SimpleClass { + constructor( + public name: string, + public value: number, + ) {} + + getData() { + return { name: this.name, value: this.value }; + } +} + +export namespace SimpleClass { + export function generate(): SimpleClass { + return new SimpleClass("test", 42); + } +} \ No newline at end of file