typia 13.1.19 → 13.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/executable/FileSystemIdentity.d.ts +23 -0
- package/lib/executable/FileSystemIdentity.js +30 -0
- package/lib/executable/FileSystemIdentity.js.map +1 -1
- package/lib/executable/FileSystemIdentity.mjs +4 -0
- package/lib/executable/FileSystemIdentity.mjs.map +1 -1
- package/lib/executable/TypiaGenerateWizard.js +15 -9
- package/lib/executable/TypiaGenerateWizard.js.map +1 -1
- package/lib/executable/TypiaGenerateWizard.mjs +11 -7
- package/lib/executable/TypiaGenerateWizard.mjs.map +1 -1
- package/lib/internal/_ProtobufReader.d.ts +18 -3
- package/lib/internal/_ProtobufReader.js +39 -11
- package/lib/internal/_ProtobufReader.js.map +1 -1
- package/lib/internal/_ProtobufReader.mjs +37 -10
- package/lib/internal/_ProtobufReader.mjs.map +1 -1
- package/lib/internal/_jsonStringifyArray.d.ts +1 -0
- package/lib/internal/_jsonStringifyArray.js +48 -0
- package/lib/internal/_jsonStringifyArray.js.map +1 -0
- package/lib/internal/_jsonStringifyArray.mjs +40 -0
- package/lib/internal/_jsonStringifyArray.mjs.map +1 -0
- package/lib/internal/_jsonStringifyElement.d.ts +1 -0
- package/lib/internal/_jsonStringifyElement.js +23 -0
- package/lib/internal/_jsonStringifyElement.js.map +1 -0
- package/lib/internal/_jsonStringifyElement.mjs +23 -0
- package/lib/internal/_jsonStringifyElement.mjs.map +1 -0
- package/lib/internal/_jsonStringifyProperty.d.ts +1 -0
- package/lib/internal/_jsonStringifyProperty.js +31 -0
- package/lib/internal/_jsonStringifyProperty.js.map +1 -0
- package/lib/internal/_jsonStringifyProperty.mjs +31 -0
- package/lib/internal/_jsonStringifyProperty.mjs.map +1 -0
- package/lib/internal/_llmApplicationFinalize.js +1 -1
- package/lib/internal/_llmApplicationFinalize.js.map +1 -1
- package/lib/internal/_llmApplicationFinalize.mjs +1 -1
- package/lib/internal/_llmApplicationFinalize.mjs.map +1 -1
- package/lib/internal/_randomFormatByte.js +24 -1
- package/lib/internal/_randomFormatByte.js.map +1 -1
- package/lib/internal/_randomFormatByte.mjs +20 -2
- package/lib/internal/_randomFormatByte.mjs.map +1 -1
- package/lib/internal/_randomFormatDate.d.ts +3 -6
- package/lib/internal/_randomFormatDate.js +2 -10
- package/lib/internal/_randomFormatDate.js.map +1 -1
- package/lib/internal/_randomFormatDate.mjs +2 -6
- package/lib/internal/_randomFormatDate.mjs.map +1 -1
- package/lib/internal/_randomFormatDatetime.d.ts +3 -6
- package/lib/internal/_randomFormatDatetime.js +25 -8
- package/lib/internal/_randomFormatDatetime.js.map +1 -1
- package/lib/internal/_randomFormatDatetime.mjs +17 -7
- package/lib/internal/_randomFormatDatetime.mjs.map +1 -1
- package/lib/internal/_randomFormatDuration.js +23 -15
- package/lib/internal/_randomFormatDuration.js.map +1 -1
- package/lib/internal/_randomFormatDuration.mjs +23 -15
- package/lib/internal/_randomFormatDuration.mjs.map +1 -1
- package/lib/internal/_randomFormatIpv4.js +31 -1
- package/lib/internal/_randomFormatIpv4.js.map +1 -1
- package/lib/internal/_randomFormatIpv4.mjs +23 -2
- package/lib/internal/_randomFormatIpv4.mjs.map +1 -1
- package/lib/internal/_randomFormatIpv6.js +57 -1
- package/lib/internal/_randomFormatIpv6.js.map +1 -1
- package/lib/internal/_randomFormatIpv6.mjs +45 -2
- package/lib/internal/_randomFormatIpv6.mjs.map +1 -1
- package/lib/internal/_randomFormatJsonPointer.js +14 -2
- package/lib/internal/_randomFormatJsonPointer.js.map +1 -1
- package/lib/internal/_randomFormatJsonPointer.mjs +13 -3
- package/lib/internal/_randomFormatJsonPointer.mjs.map +1 -1
- package/lib/internal/_randomFormatRegex.js +14 -1
- package/lib/internal/_randomFormatRegex.js.map +1 -1
- package/lib/internal/_randomFormatRegex.mjs +14 -2
- package/lib/internal/_randomFormatRegex.mjs.map +1 -1
- package/lib/internal/_randomFormatRelativeJsonPointer.js +19 -5
- package/lib/internal/_randomFormatRelativeJsonPointer.js.map +1 -1
- package/lib/internal/_randomFormatRelativeJsonPointer.mjs +21 -6
- package/lib/internal/_randomFormatRelativeJsonPointer.mjs.map +1 -1
- package/lib/internal/_randomFormatTime.js +33 -7
- package/lib/internal/_randomFormatTime.js.map +1 -1
- package/lib/internal/_randomFormatTime.mjs +37 -5
- package/lib/internal/_randomFormatTime.mjs.map +1 -1
- package/lib/internal/_randomPattern.js.map +1 -1
- package/lib/internal/_randomPattern.mjs.map +1 -1
- package/lib/internal/_randomStringLength.d.ts +41 -10
- package/lib/internal/_randomStringLength.js +49 -13
- package/lib/internal/_randomStringLength.js.map +1 -1
- package/lib/internal/_randomStringLength.mjs +48 -13
- package/lib/internal/_randomStringLength.mjs.map +1 -1
- package/lib/internal/private/__notationRename.js.map +1 -1
- package/lib/internal/private/__notationRename.mjs.map +1 -1
- package/lib/internal/private/__randomComposition.d.ts +23 -0
- package/lib/internal/private/__randomComposition.js +48 -0
- package/lib/internal/private/__randomComposition.js.map +1 -0
- package/lib/internal/private/__randomComposition.mjs +54 -0
- package/lib/internal/private/__randomComposition.mjs.map +1 -0
- package/lib/internal/private/__randomEpoch.d.ts +19 -0
- package/lib/internal/private/__randomEpoch.js +31 -0
- package/lib/internal/private/__randomEpoch.js.map +1 -0
- package/lib/internal/private/__randomEpoch.mjs +28 -0
- package/lib/internal/private/__randomEpoch.mjs.map +1 -0
- package/native/cmd/ttsc-typia/build.go +3 -0
- package/native/cmd/ttsc-typia/callable_interface_function_semantics_transform_test.go +331 -0
- package/native/cmd/ttsc-typia/callable_type_literal_boundaries_transform_test.go +1184 -0
- package/native/cmd/ttsc-typia/compare_functional_union_membership_transform_test.go +434 -0
- package/native/cmd/ttsc-typia/compare_template_literal_union_transform_test.go +241 -0
- package/native/cmd/ttsc-typia/default_library_spoof_native_identity_transform_test.go +216 -0
- package/native/cmd/ttsc-typia/json_schema_dynamic_key_determinism_transform_test.go +246 -0
- package/native/cmd/ttsc-typia/json_stringify_contextual_undefined_transform_test.go +556 -0
- package/native/cmd/ttsc-typia/lib_replacement_native_identity_transform_test.go +277 -0
- package/native/cmd/ttsc-typia/native_named_intersection_union_transform_test.go +390 -0
- package/native/cmd/ttsc-typia/node_buffer_native_exports_is_transform_test.go +526 -0
- package/native/cmd/ttsc-typia/package_declaration_native_identity_is_transform_test.go +293 -0
- package/native/cmd/ttsc-typia/protobuf_diagnostic_code_transform_test.go +167 -0
- package/native/cmd/ttsc-typia/symbol_index_domain_transform_test.go +316 -0
- package/native/cmd/ttsc-typia/transform.go +23 -0
- package/native/cmd/ttsc-typia/transform_helpers_test.go +77 -2
- package/native/cmd/ttsc-typia/user_global_native_identity_transform_test.go +484 -0
- package/native/core/factories/ProtobufFactory.go +6 -1
- package/native/core/factories/internal/metadata/MetadataHelper.go +185 -30
- package/native/core/factories/internal/metadata/emplace_metadata_object.go +25 -0
- package/native/core/factories/internal/metadata/iterate_metadata_function.go +1 -1
- package/native/core/factories/internal/metadata/iterate_metadata_intersection.go +103 -23
- package/native/core/factories/internal/metadata/iterate_metadata_map.go +3 -7
- package/native/core/factories/internal/metadata/iterate_metadata_native.go +32 -14
- package/native/core/factories/internal/metadata/iterate_metadata_set.go +3 -7
- package/native/core/programmers/compare/CompareEqualProgrammer.go +27 -13
- package/native/core/programmers/helpers/FunctionProgrammer.go +6 -13
- package/native/core/programmers/helpers/StringifyJoinder.go +129 -50
- package/native/core/programmers/helpers/joiner_branch_coverage_test.go +116 -120
- package/native/core/programmers/iterate/iterate_check_coverage_test.go +76 -158
- package/native/core/programmers/iterate/iterate_utility_coverage_test.go +231 -270
- package/native/core/programmers/iterate/json_schema_object.go +49 -7
- package/native/core/programmers/iterate/json_schema_pattern_property_order_test.go +44 -0
- package/native/core/programmers/iterate/openapi_v3_downgrader.go +34 -1
- package/native/core/programmers/iterate/template_runtime_pattern.go +11 -0
- package/native/core/programmers/json/JsonStringifyProgrammer.go +47 -6
- package/native/core/programmers/llm/LlmApplicationProgrammer.go +9 -1
- package/native/core/programmers/protobuf/ProtobufMessageProgrammer.go +1 -1
- package/native/core/schemas/metadata/MetadataCollection.go +0 -9
- package/native/core/schemas/metadata/MetadataDefaultLibrary.go +81 -0
- package/native/core/schemas/metadata/MetadataObjectType.go +7 -18
- package/native/go.mod +4 -4
- package/native/transform/features/protobuf/ProtobufMessageTransformer.go +1 -1
- package/package.json +3 -7
- package/src/executable/FileSystemIdentity.ts +33 -0
- package/src/executable/TypiaGenerateWizard.ts +18 -12
- package/src/internal/_ProtobufReader.ts +40 -11
- package/src/internal/_jsonStringifyArray.ts +50 -0
- package/src/internal/_jsonStringifyElement.ts +19 -0
- package/src/internal/_jsonStringifyProperty.ts +30 -0
- package/src/internal/_llmApplicationFinalize.ts +6 -1
- package/src/internal/_randomFormatByte.ts +30 -3
- package/src/internal/_randomFormatDate.ts +4 -20
- package/src/internal/_randomFormatDatetime.ts +34 -20
- package/src/internal/_randomFormatDuration.ts +19 -4
- package/src/internal/_randomFormatIpv4.ts +43 -3
- package/src/internal/_randomFormatIpv6.ts +67 -3
- package/src/internal/_randomFormatJsonPointer.ts +23 -3
- package/src/internal/_randomFormatRegex.ts +21 -3
- package/src/internal/_randomFormatRelativeJsonPointer.ts +23 -10
- package/src/internal/_randomFormatTime.ts +45 -12
- package/src/internal/_randomPattern.ts +4 -1
- package/src/internal/_randomStringLength.ts +61 -17
- package/src/internal/private/__notationRename.ts +1 -4
- package/src/internal/private/__randomComposition.ts +50 -0
- package/src/internal/private/__randomEpoch.ts +34 -0
- package/native/adapter/visit.go +0 -173
- package/native/adapter/visit_property_chain_edges_test.go +0 -129
- package/native/core/programmers/helpers/disable_function_programmer_declare.go +0 -10
- package/native/core/programmers/iterate/check_union_array_like.go +0 -422
- package/native/core/programmers/iterate/prune_object_properties.go +0 -105
- package/native/core/programmers/iterate/stringify_dynamic_properties.go +0 -219
- package/native/core/programmers/iterate/stringify_native.go +0 -14
- package/native/core/programmers/iterate/stringify_regular_properties.go +0 -112
- package/native/core/schemas/metadata/MetadataApplication.go +0 -41
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"fmt"
|
|
5
|
+
"os"
|
|
6
|
+
"os/exec"
|
|
7
|
+
"path/filepath"
|
|
8
|
+
"strings"
|
|
9
|
+
"testing"
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
// TestCallableInterfaceFunctionSemanticsTransform verifies declaration-syntax
|
|
13
|
+
// parity for pure callable and constructable types (#2238).
|
|
14
|
+
//
|
|
15
|
+
// TypeScript considers the call-only and construct-only interfaces in this
|
|
16
|
+
// fixture mutually assignable with their function-type aliases. Typia must
|
|
17
|
+
// therefore apply the same default and `functional: true` validator semantics
|
|
18
|
+
// to both spellings. Hybrid interfaces are a deliberate negative boundary:
|
|
19
|
+
// their data members must remain represented rather than disappearing through
|
|
20
|
+
// an over-broad signature check. The global `Function` type is the adjacent
|
|
21
|
+
// positive control for the pre-existing function-interface path.
|
|
22
|
+
//
|
|
23
|
+
// 1. Transform one source under the default and functional plugin options.
|
|
24
|
+
// 2. Exercise direct and factory validators at top level and inside holders.
|
|
25
|
+
// 3. Require alias parity, hybrid-member preservation, and global Function
|
|
26
|
+
// behavior with an exact runtime case count.
|
|
27
|
+
func TestCallableInterfaceFunctionSemanticsTransform(t *testing.T) {
|
|
28
|
+
project := compareEqualCoverProject(t, "callable-interface-function-semantics-", callableInterfaceFunctionSemanticsSource)
|
|
29
|
+
defaultJS := callableInterfaceFunctionSemanticsTransform(t, project, false)
|
|
30
|
+
functionalJS := callableInterfaceFunctionSemanticsTransform(t, project, true)
|
|
31
|
+
|
|
32
|
+
failures := []string{}
|
|
33
|
+
for name, js := range map[string]string{
|
|
34
|
+
"default": defaultJS,
|
|
35
|
+
"functional": functionalJS,
|
|
36
|
+
} {
|
|
37
|
+
for _, member := range []string{"label", "kind", "inheritedCallableLabel", "inheritedConstructableKind"} {
|
|
38
|
+
if !strings.Contains(js, member) {
|
|
39
|
+
failures = append(failures, fmt.Sprintf("%s emit erased hybrid member %q", name, member))
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
output, runtimeErr := callableInterfaceFunctionSemanticsRun(t, project, defaultJS, functionalJS)
|
|
45
|
+
if runtimeErr != nil {
|
|
46
|
+
failures = append(failures, fmt.Sprintf("runtime matrix failed: %v\n%s", runtimeErr, output))
|
|
47
|
+
}
|
|
48
|
+
const expected = "RAN 104 CASES"
|
|
49
|
+
if !strings.Contains(output, expected) {
|
|
50
|
+
failures = append(failures, fmt.Sprintf("runtime runner did not report %q; got:\n%s", expected, output))
|
|
51
|
+
}
|
|
52
|
+
if len(failures) != 0 {
|
|
53
|
+
t.Fatalf(
|
|
54
|
+
"callable-interface function-semantics mismatches:\n%s\n\ndefault emit:\n%s\n\nfunctional emit:\n%s",
|
|
55
|
+
strings.Join(failures, "\n"),
|
|
56
|
+
defaultJS,
|
|
57
|
+
functionalJS,
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
func callableInterfaceFunctionSemanticsTransform(t *testing.T, project string, functional bool) string {
|
|
63
|
+
t.Helper()
|
|
64
|
+
option := ""
|
|
65
|
+
if functional {
|
|
66
|
+
option = `,"functional":true`
|
|
67
|
+
}
|
|
68
|
+
payload := `[{"config":{"transform":"typia/lib/transform"` + option + `},"name":"typia","stage":"transform"}]`
|
|
69
|
+
out, errText, code := ttscTypiaTestCapture(func() int {
|
|
70
|
+
return runTransform([]string{
|
|
71
|
+
"--cwd", project,
|
|
72
|
+
"--tsconfig", "tsconfig.json",
|
|
73
|
+
"--file", "src/main.ts",
|
|
74
|
+
"--output", "js",
|
|
75
|
+
"--plugins-json", payload,
|
|
76
|
+
})
|
|
77
|
+
})
|
|
78
|
+
if code != 0 {
|
|
79
|
+
t.Fatalf("callable-interface transform (functional=%t) failed: code=%d stderr=\n%s", functional, code, errText)
|
|
80
|
+
}
|
|
81
|
+
return out
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
func callableInterfaceFunctionSemanticsRun(t *testing.T, project string, defaultJS string, functionalJS string) (string, error) {
|
|
85
|
+
t.Helper()
|
|
86
|
+
node, err := exec.LookPath("node")
|
|
87
|
+
if err != nil {
|
|
88
|
+
t.Skip("node executable not found")
|
|
89
|
+
return "", nil
|
|
90
|
+
}
|
|
91
|
+
runtimeDir := filepath.Join(project, "runtime")
|
|
92
|
+
if err := os.MkdirAll(runtimeDir, 0o755); err != nil {
|
|
93
|
+
t.Fatalf("mkdir runtime dir: %v", err)
|
|
94
|
+
}
|
|
95
|
+
ttscTypiaTestWriteCommonRuntimeStubs(t, runtimeDir)
|
|
96
|
+
modules := map[string]string{
|
|
97
|
+
"default.cjs": ttscTypiaTestRewriteCommonJS(t, defaultJS),
|
|
98
|
+
"functional.cjs": ttscTypiaTestRewriteCommonJS(t, functionalJS),
|
|
99
|
+
"run.cjs": callableInterfaceFunctionSemanticsRuntimeRunner,
|
|
100
|
+
}
|
|
101
|
+
for name, content := range modules {
|
|
102
|
+
if err := os.WriteFile(filepath.Join(runtimeDir, name), []byte(content), 0o644); err != nil {
|
|
103
|
+
t.Fatalf("write runtime file %s: %v", name, err)
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
cmd := exec.Command(node, filepath.Join(runtimeDir, "run.cjs"))
|
|
107
|
+
cmd.Dir = runtimeDir
|
|
108
|
+
output, err := cmd.CombinedOutput()
|
|
109
|
+
return string(output), err
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const callableInterfaceFunctionSemanticsSource = `import typia from "typia";
|
|
113
|
+
|
|
114
|
+
interface CallableInterface {
|
|
115
|
+
(value: number): string;
|
|
116
|
+
}
|
|
117
|
+
interface ConstructableInterface {
|
|
118
|
+
new (value: number): { value: number };
|
|
119
|
+
}
|
|
120
|
+
type CallableAlias = (value: number) => string;
|
|
121
|
+
type ConstructableAlias = new (value: number) => { value: number };
|
|
122
|
+
|
|
123
|
+
type Assert<T extends true> = T;
|
|
124
|
+
type Same<X, Y> = [X] extends [Y]
|
|
125
|
+
? [Y] extends [X]
|
|
126
|
+
? true
|
|
127
|
+
: false
|
|
128
|
+
: false;
|
|
129
|
+
type _CallableSpellingsAreEquivalent = Assert<Same<CallableInterface, CallableAlias>>;
|
|
130
|
+
type _ConstructableSpellingsAreEquivalent = Assert<Same<ConstructableInterface, ConstructableAlias>>;
|
|
131
|
+
|
|
132
|
+
interface InterfaceHolder {
|
|
133
|
+
callable: CallableInterface;
|
|
134
|
+
constructable: ConstructableInterface;
|
|
135
|
+
}
|
|
136
|
+
interface AliasHolder {
|
|
137
|
+
callable: CallableAlias;
|
|
138
|
+
constructable: ConstructableAlias;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
interface HybridCallable {
|
|
142
|
+
(value: number): string;
|
|
143
|
+
label: string;
|
|
144
|
+
}
|
|
145
|
+
interface HybridConstructable {
|
|
146
|
+
new (value: number): { value: number };
|
|
147
|
+
kind: string;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
interface IndexedCallable {
|
|
151
|
+
(value: number): string;
|
|
152
|
+
[key: string]: unknown;
|
|
153
|
+
}
|
|
154
|
+
interface IndexedConstructable {
|
|
155
|
+
new (value: number): { value: number };
|
|
156
|
+
[key: string]: unknown;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
interface InheritedCallableMembers {
|
|
160
|
+
inheritedCallableLabel: string;
|
|
161
|
+
}
|
|
162
|
+
interface InheritedConstructableMembers {
|
|
163
|
+
inheritedConstructableKind: string;
|
|
164
|
+
}
|
|
165
|
+
interface InheritedIndexMembers {
|
|
166
|
+
[key: string]: unknown;
|
|
167
|
+
}
|
|
168
|
+
interface InheritedNamedCallable extends InheritedCallableMembers {
|
|
169
|
+
(value: number): string;
|
|
170
|
+
}
|
|
171
|
+
interface InheritedNamedConstructable extends InheritedConstructableMembers {
|
|
172
|
+
new (value: number): { value: number };
|
|
173
|
+
}
|
|
174
|
+
interface InheritedIndexedCallable extends InheritedIndexMembers {
|
|
175
|
+
(value: number): string;
|
|
176
|
+
}
|
|
177
|
+
interface InheritedIndexedConstructable extends InheritedIndexMembers {
|
|
178
|
+
new (value: number): { value: number };
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export const directCallableInterface = (input: unknown): boolean => typia.is<CallableInterface>(input);
|
|
182
|
+
export const factoryCallableInterface = typia.createIs<CallableInterface>();
|
|
183
|
+
export const directConstructableInterface = (input: unknown): boolean => typia.is<ConstructableInterface>(input);
|
|
184
|
+
export const factoryConstructableInterface = typia.createIs<ConstructableInterface>();
|
|
185
|
+
|
|
186
|
+
export const directCallableAlias = (input: unknown): boolean => typia.is<CallableAlias>(input);
|
|
187
|
+
export const factoryCallableAlias = typia.createIs<CallableAlias>();
|
|
188
|
+
export const directConstructableAlias = (input: unknown): boolean => typia.is<ConstructableAlias>(input);
|
|
189
|
+
export const factoryConstructableAlias = typia.createIs<ConstructableAlias>();
|
|
190
|
+
|
|
191
|
+
export const directInterfaceHolder = (input: unknown): boolean => typia.is<InterfaceHolder>(input);
|
|
192
|
+
export const factoryInterfaceHolder = typia.createIs<InterfaceHolder>();
|
|
193
|
+
export const directAliasHolder = (input: unknown): boolean => typia.is<AliasHolder>(input);
|
|
194
|
+
export const factoryAliasHolder = typia.createIs<AliasHolder>();
|
|
195
|
+
|
|
196
|
+
export const directHybridCallable = (input: unknown): boolean => typia.is<HybridCallable>(input);
|
|
197
|
+
export const factoryHybridCallable = typia.createIs<HybridCallable>();
|
|
198
|
+
export const directHybridConstructable = (input: unknown): boolean => typia.is<HybridConstructable>(input);
|
|
199
|
+
export const factoryHybridConstructable = typia.createIs<HybridConstructable>();
|
|
200
|
+
|
|
201
|
+
export const directIndexedCallable = (input: unknown): boolean => typia.is<IndexedCallable>(input);
|
|
202
|
+
export const factoryIndexedCallable = typia.createIs<IndexedCallable>();
|
|
203
|
+
export const directIndexedConstructable = (input: unknown): boolean => typia.is<IndexedConstructable>(input);
|
|
204
|
+
export const factoryIndexedConstructable = typia.createIs<IndexedConstructable>();
|
|
205
|
+
|
|
206
|
+
export const directInheritedNamedCallable = (input: unknown): boolean => typia.is<InheritedNamedCallable>(input);
|
|
207
|
+
export const factoryInheritedNamedCallable = typia.createIs<InheritedNamedCallable>();
|
|
208
|
+
export const directInheritedNamedConstructable = (input: unknown): boolean => typia.is<InheritedNamedConstructable>(input);
|
|
209
|
+
export const factoryInheritedNamedConstructable = typia.createIs<InheritedNamedConstructable>();
|
|
210
|
+
export const directInheritedIndexedCallable = (input: unknown): boolean => typia.is<InheritedIndexedCallable>(input);
|
|
211
|
+
export const factoryInheritedIndexedCallable = typia.createIs<InheritedIndexedCallable>();
|
|
212
|
+
export const directInheritedIndexedConstructable = (input: unknown): boolean => typia.is<InheritedIndexedConstructable>(input);
|
|
213
|
+
export const factoryInheritedIndexedConstructable = typia.createIs<InheritedIndexedConstructable>();
|
|
214
|
+
|
|
215
|
+
export const directGlobalFunction = (input: unknown): boolean => typia.is<Function>(input);
|
|
216
|
+
export const factoryGlobalFunction = typia.createIs<Function>();
|
|
217
|
+
export const directGlobalFunctionHolder = (input: unknown): boolean => typia.is<{ fn: Function }>(input);
|
|
218
|
+
export const factoryGlobalFunctionHolder = typia.createIs<{ fn: Function }>();
|
|
219
|
+
`
|
|
220
|
+
|
|
221
|
+
const callableInterfaceFunctionSemanticsRuntimeRunner = `const defaults = require("./default.cjs");
|
|
222
|
+
const functional = require("./functional.cjs");
|
|
223
|
+
|
|
224
|
+
let ran = 0;
|
|
225
|
+
const failures = [];
|
|
226
|
+
const eq = (name, actual, expected) => {
|
|
227
|
+
ran += 1;
|
|
228
|
+
if (actual !== expected) {
|
|
229
|
+
failures.push(name + ": expected " + expected + " but got " + actual);
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
const callable = (value) => String(value);
|
|
234
|
+
class Constructable {
|
|
235
|
+
constructor(value) {
|
|
236
|
+
this.value = value;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
const holder = { callable, constructable: Constructable };
|
|
240
|
+
const placeholders = { callable: {}, constructable: {} };
|
|
241
|
+
|
|
242
|
+
const topLevelRows = [
|
|
243
|
+
["directCallableInterface", callable, {}],
|
|
244
|
+
["factoryCallableInterface", callable, {}],
|
|
245
|
+
["directConstructableInterface", Constructable, {}],
|
|
246
|
+
["factoryConstructableInterface", Constructable, {}],
|
|
247
|
+
["directCallableAlias", callable, {}],
|
|
248
|
+
["factoryCallableAlias", callable, {}],
|
|
249
|
+
["directConstructableAlias", Constructable, {}],
|
|
250
|
+
["factoryConstructableAlias", Constructable, {}],
|
|
251
|
+
];
|
|
252
|
+
for (const [name, real, placeholder] of topLevelRows) {
|
|
253
|
+
eq("default " + name + " real", defaults[name](real), true);
|
|
254
|
+
eq("default " + name + " placeholder", defaults[name](placeholder), true);
|
|
255
|
+
eq("functional " + name + " real", functional[name](real), true);
|
|
256
|
+
eq("functional " + name + " placeholder", functional[name](placeholder), false);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
for (const name of [
|
|
260
|
+
"directInterfaceHolder",
|
|
261
|
+
"factoryInterfaceHolder",
|
|
262
|
+
"directAliasHolder",
|
|
263
|
+
"factoryAliasHolder",
|
|
264
|
+
]) {
|
|
265
|
+
eq("default " + name + " real", defaults[name](holder), true);
|
|
266
|
+
eq("default " + name + " placeholders", defaults[name](placeholders), true);
|
|
267
|
+
eq("functional " + name + " real", functional[name](holder), true);
|
|
268
|
+
eq("functional " + name + " placeholders", functional[name](placeholders), false);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Hybrid interfaces stay outside the pure-function classification. A real
|
|
272
|
+
// function or constructor missing the declared data member and a plain object
|
|
273
|
+
// carrying only that member are both incomplete values. Keeping both negative
|
|
274
|
+
// twins prevents a signature-based fix from erasing the member or the callable
|
|
275
|
+
// side of the TypeScript shape.
|
|
276
|
+
for (const mod of [defaults, functional]) {
|
|
277
|
+
for (const name of ["directHybridCallable", "factoryHybridCallable"]) {
|
|
278
|
+
eq(name + " callable missing data member", mod[name](callable), false);
|
|
279
|
+
eq(name + " data member without callability", mod[name]({ label: "kept" }), false);
|
|
280
|
+
}
|
|
281
|
+
for (const name of ["directHybridConstructable", "factoryHybridConstructable"]) {
|
|
282
|
+
eq(name + " constructor missing data member", mod[name](Constructable), false);
|
|
283
|
+
eq(name + " data member without constructability", mod[name]({ kind: "kept" }), false);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// Index signatures are an independent hybrid boundary, and both named and
|
|
288
|
+
// indexed boundaries can arrive through interface inheritance. These valid
|
|
289
|
+
// function/class values intentionally omit the full hybrid shape, so existing
|
|
290
|
+
// structural handling rejects them. If either boundary is erased and the type
|
|
291
|
+
// is over-classified as a pure function, default mode skips it and functional
|
|
292
|
+
// mode accepts its typeof-function value.
|
|
293
|
+
const hybridBoundaryRows = [
|
|
294
|
+
["directIndexedCallable", callable],
|
|
295
|
+
["factoryIndexedCallable", callable],
|
|
296
|
+
["directIndexedConstructable", Constructable],
|
|
297
|
+
["factoryIndexedConstructable", Constructable],
|
|
298
|
+
["directInheritedNamedCallable", callable],
|
|
299
|
+
["factoryInheritedNamedCallable", callable],
|
|
300
|
+
["directInheritedNamedConstructable", Constructable],
|
|
301
|
+
["factoryInheritedNamedConstructable", Constructable],
|
|
302
|
+
["directInheritedIndexedCallable", callable],
|
|
303
|
+
["factoryInheritedIndexedCallable", callable],
|
|
304
|
+
["directInheritedIndexedConstructable", Constructable],
|
|
305
|
+
["factoryInheritedIndexedConstructable", Constructable],
|
|
306
|
+
];
|
|
307
|
+
for (const [mode, mod] of [["default", defaults], ["functional", functional]]) {
|
|
308
|
+
for (const [name, value] of hybridBoundaryRows) {
|
|
309
|
+
eq(mode + " " + name + " incomplete hybrid", mod[name](value), false);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// The existing global Function path remains the positive interface control.
|
|
314
|
+
for (const name of ["directGlobalFunction", "factoryGlobalFunction"]) {
|
|
315
|
+
eq("default " + name + " real", defaults[name](callable), true);
|
|
316
|
+
eq("default " + name + " placeholder", defaults[name]({}), true);
|
|
317
|
+
eq("functional " + name + " real", functional[name](callable), true);
|
|
318
|
+
eq("functional " + name + " placeholder", functional[name]({}), false);
|
|
319
|
+
}
|
|
320
|
+
for (const name of ["directGlobalFunctionHolder", "factoryGlobalFunctionHolder"]) {
|
|
321
|
+
eq("default " + name + " real", defaults[name]({ fn: callable }), true);
|
|
322
|
+
eq("default " + name + " placeholder", defaults[name]({ fn: {} }), true);
|
|
323
|
+
eq("functional " + name + " real", functional[name]({ fn: callable }), true);
|
|
324
|
+
eq("functional " + name + " placeholder", functional[name]({ fn: {} }), false);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
console.log("RAN " + ran + " CASES");
|
|
328
|
+
if (failures.length !== 0) {
|
|
329
|
+
throw new Error("MISMATCHES:\n" + failures.join("\n"));
|
|
330
|
+
}
|
|
331
|
+
`
|