Skip to content

Commit

Permalink
Merge pull request #238 from samchon/features/enum
Browse files Browse the repository at this point in the history
Close #237 - support enumeration typed property
  • Loading branch information
samchon authored Oct 11, 2022
2 parents f43ca9c + 06ec1c4 commit 8b4895e
Show file tree
Hide file tree
Showing 17 changed files with 243 additions and 21 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "typescript-json",
"version": "3.3.9",
"version": "3.3.10",
"description": "Runtime type checkers and 5x faster JSON.stringify() function",
"main": "lib/index.js",
"typings": "lib/index.d.ts",
Expand Down
45 changes: 25 additions & 20 deletions src/factories/internal/emplace_metadata_object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,16 @@ export const emplace_metadata_object =
// PREPARE ASSETS
const isClass: boolean = parent.isClass();
const pred: (node: ts.Declaration) => boolean = isClass
? (node) => ts.isParameter(node) || ts.isPropertyDeclaration(node)
? (node) => {
const kind: ts.SyntaxKind | undefined = node
.getChildren()[0]
?.getChildren()[0]?.kind;
return (
kind !== ts.SyntaxKind.PrivateKeyword &&
kind !== ts.SyntaxKind.ProtectedKeyword &&
(ts.isParameter(node) || ts.isPropertyDeclaration(node))
);
}
: (node) =>
ts.isPropertyDeclaration(node) ||
ts.isPropertyAssignment(node) ||
Expand Down Expand Up @@ -71,36 +80,32 @@ export const emplace_metadata_object =
//----
// REGULAR PROPERTIES
//----
for (const prop of parent.getProperties()) {
for (const prop of parent.getApparentProperties()) {
// CHECK NODE IS A FORMAL PROPERTY
const node: ts.PropertyDeclaration | undefined =
(prop.getDeclarations() || [])[0] as
const [node, type] = (() => {
const node = (prop.getDeclarations() || [])[0] as
| ts.PropertyDeclaration
| undefined;

if (!node || !pred(node)) continue;

// CHECK NOT PRIVATE OR PROTECTED MEMBER
if (isClass) {
const kind: ts.SyntaxKind | undefined = node
.getChildren()[0]
?.getChildren()[0]?.kind;
if (
kind === ts.SyntaxKind.PrivateKeyword ||
kind === ts.SyntaxKind.ProtectedKeyword
)
continue;
}
const type: ts.Type | undefined = node
? checker.getTypeOfSymbolAtLocation(prop, node)
: "getTypeOfPropertyOfType" in checker
? (checker as any).getTypeOfPropertyOfType(
parent,
prop.name,
)
: undefined;
return [node, type];
})();
if ((node && pred(node) === false) || type === undefined) continue;

// GET EXACT TYPE
const type: ts.Type = checker.getTypeOfSymbolAtLocation(prop, node);
const key: Metadata = MetadataHelper.literal_to_metadata(prop.name);
const value: Metadata = explore_metadata(checker)(options)(
collection,
)(type, false);

// INSERT WITH REQUIRED CONFIGURATION
if (node.questionToken) Writable(value).required = false;
if (node?.questionToken) Writable(value).required = false;
insert(key)(value)(() => `${obj.name}.${prop.name}`)(prop);
}

Expand Down
19 changes: 19 additions & 0 deletions test/features/assert/test_assert_dynamic_constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import TSON from "../../../src";
import { DynamicConstant } from "../../structures/DynamicConstant";
import { _test_assert } from "./_test_assert";

export const test_assert_dynamic_constant = _test_assert(
"dynamic constant",
DynamicConstant.generate,
(input) => TSON.assertType(input),
[
(input) => {
input["a"] = "zero" as any;
return "$input.a";
},
(input) => {
input["b"] = null!;
return "$input.b";
},
],
);
19 changes: 19 additions & 0 deletions test/features/assert/test_assert_dynamic_enumeration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import TSON from "../../../src";
import { DynamicEnumeration } from "../../structures/DynamicEnumeration";
import { _test_assert } from "./_test_assert";

export const test_assert_dynamic_enumeration = _test_assert(
"dynamic enumeration",
DynamicEnumeration.generate,
(input) => TSON.assertType(input),
[
(input) => {
input["fr"] = null!;
return "$input.fr";
},
(input) => {
input["ar"] = 0 as any;
return "$input.ar";
},
],
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import TSON from "../../../src";
import { DynamicConstant } from "../../structures/DynamicConstant";
import { _test_assert_equals } from "./_test_assert_equals";

export const test_assert_equals_dynamic_constant = _test_assert_equals(
"dynamic constant",
DynamicConstant.generate,
(input) => TSON.assertEquals(input),
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import TSON from "../../../src";
import { DynamicEnumeration } from "../../structures/DynamicEnumeration";
import { _test_assert_equals } from "./_test_assert_equals";

export const test_assert_equals_dynamic_enumeration = _test_assert_equals(
"dynamic enumeration",
DynamicEnumeration.generate,
(input) => TSON.assertEquals(input),
);
9 changes: 9 additions & 0 deletions test/features/equals/test_equals_dynamic_constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import TSON from "../../../src";
import { DynamicConstant } from "../../structures/DynamicConstant";
import { _test_equals } from "./_test_equals";

export const test_equals_dynamic_constant = _test_equals(
"dynamic constant",
DynamicConstant.generate,
(input) => TSON.equals(input),
);
9 changes: 9 additions & 0 deletions test/features/equals/test_equals_dynamic_enumeration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import TSON from "../../../src";
import { DynamicEnumeration } from "../../structures/DynamicEnumeration";
import { _test_equals } from "./_test_equals";

export const test_equals_dynamic_enumeration = _test_equals(
"dynamic enumeration",
DynamicEnumeration.generate,
(input) => TSON.equals(input),
);
10 changes: 10 additions & 0 deletions test/features/is/test_is_dynamic_constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import TSON from "../../../src";
import { DynamicConstant } from "../../structures/DynamicConstant";
import { _test_is } from "./_test_is";

export const test_is_dynamic_constant = _test_is(
"dynamic constant",
DynamicConstant.generate,
(input) => TSON.is(input),
[(input) => (input["a"] = "zero" as any), (input) => (input["b"] = null!)],
);
10 changes: 10 additions & 0 deletions test/features/is/test_is_dynamic_enumeration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import TSON from "../../../src";
import { DynamicEnumeration } from "../../structures/DynamicEnumeration";
import { _test_is } from "./_test_is";

export const test_is_dynamic_enumeration = _test_is(
"dynamic enumeration",
DynamicEnumeration.generate,
(input) => TSON.is(input),
[(input) => (input["fr"] = null!), (input) => (input["ar"] = 0 as any)],
);
19 changes: 19 additions & 0 deletions test/features/validate/test_assert_dynamic_constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import TSON from "../../../src";
import { DynamicConstant } from "../../structures/DynamicConstant";
import { _test_validate } from "./_test_validate";

export const test_validate_dynamic_constant = _test_validate(
"dynamic constant",
DynamicConstant.generate,
(input) => TSON.validate(input),
[
(input) => {
input["a"] = "zero" as any;
return ["$input.a"];
},
(input) => {
input["b"] = null!;
return ["$input.b"];
},
],
);
19 changes: 19 additions & 0 deletions test/features/validate/test_assert_dynamic_enumeration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import TSON from "../../../src";
import { DynamicEnumeration } from "../../structures/DynamicEnumeration";
import { _test_validate } from "./_test_validate";

export const test_validate_dynamic_enumeration = _test_validate(
"dynamic enumeration",
DynamicEnumeration.generate,
(input) => TSON.validate(input),
[
(input) => {
input["fr"] = null!;
return ["$input.fr"];
},
(input) => {
input["ar"] = 0 as any;
return ["$input.ar"];
},
],
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import TSON from "../../../src";
import { DynamicConstant } from "../../structures/DynamicConstant";
import { _test_validate_equals } from "./_test_validate_equals";

export const test_validate_equals_dynamic_constant = _test_validate_equals(
"dynamic constant",
DynamicConstant.generate,
(input) => TSON.validateEquals(input),
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import TSON from "../../../src";
import { DynamicEnumeration } from "../../structures/DynamicEnumeration";
import { _test_validate_equals } from "./_test_validate_equals";

export const test_validate_equals_dynamic_enumeration = _test_validate_equals(
"dynamic enumeration",
DynamicEnumeration.generate,
(input) => TSON.validateEquals(input),
);
28 changes: 28 additions & 0 deletions test/issues/237.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { equals, is } from "../../src";

const enum LanguageCode {
Arabic = "ar",
ChineseSimp = "zh-Hans",
ChineseTrad = "zh-Hant",
English = "en",
French = "fr",
German = "de",
Japanese = "ja",
Korean = "ko", // <-- this line
Portuguese = "pt",
Russian = "ru",
}

type DynamicEnumeration = {
[P in LanguageCode]?: string;
};

const data: DynamicEnumeration = {
en: "Line 1",
ko: "1호선", // <-- this line
"zh-Hans": "1号线",
"zh-Hant": "1號線",
};
(data as any).kr = "2호선";
console.log("is", is(data));
console.log("equals", equals(data));
13 changes: 13 additions & 0 deletions test/structures/DynamicConstant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export type DynamicConstant = {
[P in "a" | "b" | "c" | "d"]: number;
};
export namespace DynamicConstant {
export function generate(): DynamicConstant {
return {
a: 1,
b: 2,
c: 3,
d: 4,
};
}
}
26 changes: 26 additions & 0 deletions test/structures/DynamicEnumeration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
export type DynamicEnumeration = {
[P in DynamicEnumeration.LanguageCode]?: string;
};
export namespace DynamicEnumeration {
export enum LanguageCode {
Arabic = "ar",
ChineseSimp = "zh-Hans",
ChineseTrad = "zh-Hant",
English = "en",
French = "fr",
German = "de",
Japanese = "ja",
Korean = "ko", // <-- this line
Portuguese = "pt",
Russian = "ru",
}

export function generate(): DynamicEnumeration {
return {
en: "Line 1",
ko: "1호선 ",
"zh-Hans": "1号线",
"zh-Hant": "1號線",
};
}
}

0 comments on commit 8b4895e

Please sign in to comment.