Skip to content

Commit

Permalink
Merge pull request #994 from samchon/features/implicit
Browse files Browse the repository at this point in the history
Fix `typia.functional` module for async or implicit return type case.
  • Loading branch information
samchon authored Mar 6, 2024
2 parents b6aa134 + 823c52a commit 4b021e7
Show file tree
Hide file tree
Showing 20 changed files with 168 additions and 186 deletions.
2 changes: 1 addition & 1 deletion benchmark/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,6 @@
"suppress-warnings": "^1.0.2",
"tstl": "^2.5.13",
"uuid": "^9.0.1",
"typia": "D:\\github\\samchon\\typia\\typia-5.5.0.tgz"
"typia": "D:\\github\\samchon\\typia\\typia-5.5.1.tgz"
}
}
7 changes: 4 additions & 3 deletions debug/features/functional.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import fs from "fs";
import typia from "typia";

type Something = Promise<number>;
const plus = async (x: number, y: number): Something => x + y;

try {
fs.mkdirSync(__dirname + "/../bin");
} catch {}
const func = typia.functional.validateFunction(
(x: number, y: number): number => x + y,
);
const func = typia.functional.isReturn(plus);
fs.writeFileSync(`${__dirname}/../bin/functional.js`, func.toString(), "utf8");

console.log(func(3, 4));
2 changes: 1 addition & 1 deletion debug/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@
"typescript": "^5.3.2"
},
"dependencies": {
"typia": "D:\\github\\samchon\\typia\\typia-5.5.0-dev.20240305.tgz"
"typia": "D:\\github\\samchon\\typia\\typia-5.5.1-dev.20240307-2.tgz"
}
}
2 changes: 1 addition & 1 deletion errors/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@
"typescript": "^5.3.2"
},
"dependencies": {
"typia": "D:\\github\\samchon\\typia\\typia-5.5.0.tgz"
"typia": "D:\\github\\samchon\\typia\\typia-5.5.1.tgz"
}
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "typia",
"version": "5.5.0",
"version": "5.5.1",
"description": "Superfast runtime validators with only one line",
"main": "lib/index.js",
"typings": "lib/index.d.ts",
Expand Down
4 changes: 2 additions & 2 deletions packages/typescript-json/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "typescript-json",
"version": "5.5.0",
"version": "5.5.1",
"description": "Superfast runtime validators with only one line",
"main": "lib/index.js",
"typings": "lib/index.d.ts",
Expand Down Expand Up @@ -62,7 +62,7 @@
},
"homepage": "https://typia.io",
"dependencies": {
"typia": "5.5.0"
"typia": "5.5.1"
},
"peerDependencies": {
"typescript": ">=4.8.0 <5.5.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,7 @@ export namespace FunctionalAssertFunctionProgrammer {
const wrapper = errorFactoryWrapper(modulo)(declaration.parameters)(init);
const { async, returns } = FunctionAssertReturnProgrammer.returnStatement(
project,
)(modulo)(equals)(
expression,
declaration.type,
declaration.parameters.map((p) =>
ts.factory.createIdentifier(p.name.getText()),
),
wrapper.name,
);
)(modulo)(equals)(expression, declaration, wrapper.name);
return ts.factory.createArrowFunction(
async
? [ts.factory.createModifier(ts.SyntaxKind.AsyncKeyword)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { IProject } from "../../transformers/IProject";

import { AssertProgrammer } from "../AssertProgrammer";
import { FunctionalAssertFunctionProgrammer } from "./FunctionalAssertFunctionProgrammer";
import { FunctionalGeneralProgrammer } from "./internal/FunctionalGeneralProgrammer";

export namespace FunctionalAssertParametersProgrammer {
export const write =
Expand All @@ -20,13 +21,9 @@ export namespace FunctionalAssertParametersProgrammer {
const wrapper = FunctionalAssertFunctionProgrammer.errorFactoryWrapper(
modulo,
)(declaration.parameters)(init);
const async: boolean = (() => {
if (declaration.type === undefined) return false;
const type: ts.Type = project.checker.getTypeFromTypeNode(
declaration.type,
);
return type.isTypeParameter() && type.symbol.name === "Promise";
})();
const { async } = FunctionalGeneralProgrammer.getReturnType(
project.checker,
)(declaration);
return ts.factory.createArrowFunction(
async
? [ts.factory.createModifier(ts.SyntaxKind.AsyncKeyword)]
Expand Down
30 changes: 9 additions & 21 deletions src/programmers/functional/FunctionalAssertReturnProgrammer.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import ts from "typescript";

import { TypeFactory } from "../../factories/TypeFactory";

import { IProject } from "../../transformers/IProject";

import { AssertProgrammer } from "../AssertProgrammer";
import { FunctionalAssertFunctionProgrammer } from "./FunctionalAssertFunctionProgrammer";
import { FunctionalGeneralProgrammer } from "./internal/FunctionalGeneralProgrammer";

export namespace FunctionAssertReturnProgrammer {
export const write =
Expand All @@ -22,14 +21,7 @@ export namespace FunctionAssertReturnProgrammer {
)(declaration.parameters)(init);
const { async, returns: statement } = returnStatement(project)(modulo)(
equals,
)(
expression,
declaration.type,
declaration.parameters.map((p) =>
ts.factory.createIdentifier(p.name.getText()),
),
wrapper.name,
);
)(expression, declaration, wrapper.name);
return ts.factory.createArrowFunction(
async
? [ts.factory.createModifier(ts.SyntaxKind.AsyncKeyword)]
Expand All @@ -48,25 +40,21 @@ export namespace FunctionAssertReturnProgrammer {
(equals: boolean) =>
(
expression: ts.Expression,
typeNode: ts.TypeNode | undefined,
argumentExpressions: ts.Expression[],
declaration: ts.FunctionDeclaration,
wrapper: string,
): {
async: boolean;
returns: ts.ReturnStatement;
} => {
const [type, async]: [ts.Type, boolean] = (() => {
const type: ts.Type = project.checker.getTypeFromTypeNode(
typeNode ?? TypeFactory.keyword("any"),
);
return type.isTypeParameter() && type.symbol.name === "Promise"
? [type.aliasTypeArguments![0]!, true]
: [type, false];
})();
const { type, async } = FunctionalGeneralProgrammer.getReturnType(
project.checker,
)(declaration);
const caller: ts.CallExpression = ts.factory.createCallExpression(
expression,
undefined,
argumentExpressions,
declaration.parameters.map((p) =>
ts.factory.createIdentifier(p.name.getText()),
),
);
return {
async,
Expand Down
11 changes: 6 additions & 5 deletions src/programmers/functional/FunctionalIsFunctionProgrammer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ export namespace FunctionalIsFunctionProgrammer {
: undefined,
undefined,
declaration.parameters,
ts.factory.createUnionTypeNode([
declaration.type ??
ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword),
ts.factory.createTypeReferenceNode("null"),
]),
declaration.type
? ts.factory.createUnionTypeNode([
declaration.type,
ts.factory.createTypeReferenceNode("null"),
])
: undefined,
undefined,
ts.factory.createBlock(
[
Expand Down
21 changes: 10 additions & 11 deletions src/programmers/functional/FunctionalIsParametersProgrammer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { TypeFactory } from "../../factories/TypeFactory";
import { IProject } from "../../transformers/IProject";

import { IsProgrammer } from "../IsProgrammer";
import { FunctionalGeneralProgrammer } from "./internal/FunctionalGeneralProgrammer";

export namespace FunctionalIsParametersProgrammer {
export const write =
Expand All @@ -15,23 +16,21 @@ export namespace FunctionalIsParametersProgrammer {
expression: ts.Expression,
declaration: ts.FunctionDeclaration,
): ts.ArrowFunction => {
const async: boolean = (() => {
if (declaration.type === undefined) return false;
const type: ts.Type = project.checker.getTypeFromTypeNode(
declaration.type,
);
return type.isTypeParameter() && type.symbol.name === "Promise";
})();
const { async } = FunctionalGeneralProgrammer.getReturnType(
project.checker,
)(declaration);
return ts.factory.createArrowFunction(
async
? [ts.factory.createModifier(ts.SyntaxKind.AsyncKeyword)]
: undefined,
undefined,
declaration.parameters,
ts.factory.createUnionTypeNode([
declaration.type ?? TypeFactory.keyword("any"),
ts.factory.createTypeReferenceNode("null"),
]),
declaration.type
? ts.factory.createUnionTypeNode([
declaration.type,
ts.factory.createTypeReferenceNode("null"),
])
: undefined,
undefined,
ts.factory.createBlock(
[
Expand Down
23 changes: 10 additions & 13 deletions src/programmers/functional/FunctionalIsReturnProgrammer.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import ts from "typescript";

import { StatementFactory } from "../../factories/StatementFactory";
import { TypeFactory } from "../../factories/TypeFactory";

import { IProject } from "../../transformers/IProject";

import { StringUtil } from "../../utils/StringUtil";

import { IsProgrammer } from "../IsProgrammer";
import { FunctionalGeneralProgrammer } from "./internal/FunctionalGeneralProgrammer";

export namespace FunctionalIsReturnProgrammer {
export const write =
Expand All @@ -28,10 +28,12 @@ export namespace FunctionalIsReturnProgrammer {
: undefined,
undefined,
declaration.parameters,
ts.factory.createUnionTypeNode([
declaration.type ?? TypeFactory.keyword("any"),
ts.factory.createTypeReferenceNode("null"),
]),
declaration.type
? ts.factory.createUnionTypeNode([
declaration.type,
ts.factory.createTypeReferenceNode("null"),
])
: undefined,
undefined,
ts.factory.createBlock(statements, true),
);
Expand All @@ -48,14 +50,9 @@ export namespace FunctionalIsReturnProgrammer {
async: boolean;
statements: ts.Statement[];
} => {
const [type, async]: [ts.Type, boolean] = (() => {
const type: ts.Type = project.checker.getTypeFromTypeNode(
declaration.type ?? TypeFactory.keyword("any"),
);
return type.isTypeParameter() && type.symbol.name === "Promise"
? [type.aliasTypeArguments![0]!, true]
: [type, false];
})();
const { type, async } = FunctionalGeneralProgrammer.getReturnType(
project.checker,
)(declaration);
const caller: ts.CallExpression = ts.factory.createCallExpression(
expression,
undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { StringUtil } from "../../utils/StringUtil";

import { ValidateProgrammer } from "../ValidateProgrammer";
import { FunctionalValidateFunctionProgrammer } from "./FunctionalValidateFunctionProgrammer";
import { FunctionalGeneralProgrammer } from "./internal/FunctionalGeneralProgrammer";

export namespace FunctionalValidateParametersProgrammer {
export const write =
Expand All @@ -20,13 +21,9 @@ export namespace FunctionalValidateParametersProgrammer {
expression: ts.Expression,
declaration: ts.FunctionDeclaration,
): ts.ArrowFunction => {
const async: boolean = (() => {
if (declaration.type === undefined) return false;
const type: ts.Type = project.checker.getTypeFromTypeNode(
declaration.type,
);
return type.isTypeParameter() && type.symbol.name === "Promise";
})();
const { async } = FunctionalGeneralProgrammer.getReturnType(
project.checker,
)(declaration);
const caller: ts.CallExpression = ts.factory.createCallExpression(
expression,
undefined,
Expand Down
13 changes: 4 additions & 9 deletions src/programmers/functional/FunctionalValidateReturnProgrammer.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import ts from "typescript";

import { StatementFactory } from "../../factories/StatementFactory";
import { TypeFactory } from "../../factories/TypeFactory";

import { IProject } from "../../transformers/IProject";

import { StringUtil } from "../../utils/StringUtil";

import { ValidateProgrammer } from "../ValidateProgrammer";
import { FunctionalValidateFunctionProgrammer } from "./FunctionalValidateFunctionProgrammer";
import { FunctionalGeneralProgrammer } from "./internal/FunctionalGeneralProgrammer";

export namespace FunctionalValidateReturnProgrammer {
export const write =
Expand Down Expand Up @@ -55,14 +55,9 @@ export namespace FunctionalValidateReturnProgrammer {
async: boolean;
statements: ts.Statement[];
} => {
const [type, async]: [ts.Type, boolean] = (() => {
const type: ts.Type = project.checker.getTypeFromTypeNode(
declaration.type ?? TypeFactory.keyword("any"),
);
return type.isTypeParameter() && type.symbol.name === "Promise"
? [type.aliasTypeArguments![0]!, true]
: [type, false];
})();
const { type, async } = FunctionalGeneralProgrammer.getReturnType(
project.checker,
)(declaration);
const caller: ts.CallExpression = ts.factory.createCallExpression(
expression,
undefined,
Expand Down
32 changes: 32 additions & 0 deletions src/programmers/functional/internal/FunctionalGeneralProgrammer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import ts from "typescript";

import { TypeFactory } from "../../../factories/TypeFactory";

export namespace FunctionalGeneralProgrammer {
export interface IOutput {
type: ts.Type;
async: boolean;
}
export const getReturnType =
(checker: ts.TypeChecker) =>
(declaration: ts.FunctionDeclaration): IOutput => {
const signature: ts.Signature | undefined =
checker.getSignatureFromDeclaration(declaration);
const type: ts.Type =
signature?.getReturnType() ??
checker.getTypeFromTypeNode(TypeFactory.keyword("any"));

if (type.symbol?.name === "Promise") {
const generic: readonly ts.Type[] = checker.getTypeArguments(
type as ts.TypeReference,
);
return generic.length === 1
? { type: generic[0]!, async: true }
: {
type: checker.getTypeFromTypeNode(TypeFactory.keyword("any")),
async: false,
};
}
return { type, async: false };
};
}
2 changes: 1 addition & 1 deletion test/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,6 @@
"suppress-warnings": "^1.0.2",
"tstl": "^2.5.13",
"uuid": "^9.0.1",
"typia": "D:\\github\\samchon\\typia\\typia-5.5.0.tgz"
"typia": "D:\\github\\samchon\\typia\\typia-5.5.1.tgz"
}
}
Loading

0 comments on commit 4b021e7

Please sign in to comment.