@formspec/dsl 0.1.0-alpha.5 → 0.1.0-alpha.6
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.
|
@@ -50,8 +50,18 @@ expectType({});
|
|
|
50
50
|
// =============================================================================
|
|
51
51
|
// InferSchema tests - Conditionals
|
|
52
52
|
// =============================================================================
|
|
53
|
-
// Test fields inside conditionals
|
|
53
|
+
// Test fields inside conditionals - should be optional
|
|
54
54
|
const conditionalForm = formspec(field.enum("type", ["personal", "business"]), when(is("type", "business"), field.text("company")));
|
|
55
|
+
// company is optional since it's inside a conditional
|
|
56
|
+
expectType({});
|
|
57
|
+
// Test multiple conditionals - all conditional fields should be optional
|
|
58
|
+
const multiConditionalForm = formspec(field.enum("accountType", ["personal", "business"]), when(is("accountType", "personal"), field.text("ssn")), when(is("accountType", "business"), field.text("ein"), field.text("companyName")));
|
|
59
|
+
expectType({});
|
|
60
|
+
// Test conditional inside group - still optional
|
|
61
|
+
const conditionalInGroupForm = formspec(group("Details", field.text("name"), when(is("showExtra", true), field.text("extra"))), field.boolean("showExtra"));
|
|
62
|
+
expectType({});
|
|
63
|
+
// Test group inside conditional - all fields optional
|
|
64
|
+
const groupInConditionalForm = formspec(field.boolean("showAddress"), when(is("showAddress", true), group("Address", field.text("street"), field.text("city"))));
|
|
55
65
|
expectType({});
|
|
56
66
|
// =============================================================================
|
|
57
67
|
// InferSchema tests - Array fields
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inference.test-d.js","sourceRoot":"","sources":["../../src/__tests__/inference.test-d.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAW/D,gFAAgF;AAChF,wBAAwB;AACxB,gFAAgF;AAEhF,mCAAmC;AACnC,UAAU,CAAS,EAAwC,CAAC,CAAC;AAE7D,qCAAqC;AACrC,UAAU,CAAS,EAAyC,CAAC,CAAC;AAE9D,uCAAuC;AACvC,UAAU,CAAU,EAA6C,CAAC,CAAC;AAEnE,mDAAmD;AACnD,UAAU,CACR,EAAoF,CACrF,CAAC;AAIF,UAAU,CACR,EAGG,CACJ,CAAC;AAIF,UAAU,CACR,EAA4D,CAC7D,CAAC;AAIF,UAAU,CACR,EAA2D,CAC5D,CAAC;AAEF,gFAAgF;AAChF,mCAAmC;AACnC,gFAAgF;AAEhF,yBAAyB;AACzB,MAAM,eAAe,GAAG,QAAQ,CAC9B,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CACnB,CAAC;AAEF,UAAU,CAAmB,EAAsB,CAAC,CAAC;AAErD,6BAA6B;AAC7B,MAAM,cAAc,GAAG,QAAQ,CAC7B,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAClB,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EACnB,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CACxB,CAAC;AAEF,UAAU,CAAiD,EAA0B,CAAC,CAAC;AAEvF,gFAAgF;AAChF,kCAAkC;AAClC,gFAAgF;AAEhF,yBAAyB;AACzB,MAAM,QAAQ,GAAG,QAAQ,CACvB,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAU,CAAC,CACzD,CAAC;AAEF,UAAU,CAAwC,EAAgB,CAAC,CAAC;AAEpE,6CAA6C;AAC7C,MAAM,cAAc,GAAG,QAAQ,CAC7B,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE;IACrB,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE;IACpC,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,EAAE;CAC9B,CAAC,CACZ,CAAC;AAEF,UAAU,CAA+B,EAAsB,CAAC,CAAC;AAEjE,gFAAgF;AAChF,6BAA6B;AAC7B,gFAAgF;AAEhF,4BAA4B;AAC5B,MAAM,SAAS,GAAG,QAAQ,CACxB,KAAK,CAAC,UAAU,EACd,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAClB,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CACpB,EACD,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CACvB,CAAC;AAEF,UAAU,CAAkD,EAAiB,CAAC,CAAC;AAE/E,gFAAgF;AAChF,mCAAmC;AACnC,gFAAgF;AAEhF,
|
|
1
|
+
{"version":3,"file":"inference.test-d.js","sourceRoot":"","sources":["../../src/__tests__/inference.test-d.ts"],"names":[],"mappings":"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"}
|
package/dist/dsl.d.ts
CHANGED
|
@@ -63,6 +63,41 @@ export { EnumOption }
|
|
|
63
63
|
|
|
64
64
|
export { EnumOptionValue }
|
|
65
65
|
|
|
66
|
+
/**
|
|
67
|
+
* Extracts fields that ARE inside conditionals.
|
|
68
|
+
* These fields may or may not be visible and should be optional in the inferred schema.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```typescript
|
|
72
|
+
* // Given a form with conditional fields:
|
|
73
|
+
* const form = formspec(
|
|
74
|
+
* field.text("name"), // non-conditional (skipped)
|
|
75
|
+
* when(is("type", "business"),
|
|
76
|
+
* field.text("company"), // conditional (extracted)
|
|
77
|
+
* field.text("taxId"), // conditional (extracted)
|
|
78
|
+
* ),
|
|
79
|
+
* );
|
|
80
|
+
*
|
|
81
|
+
* // ExtractConditionalFields extracts: TextField<"company"> | TextField<"taxId">
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export declare type ExtractConditionalFields<E> = E extends AnyField ? never : E extends Group<infer Elements> ? ExtractConditionalFieldsFromArray<Elements> : E extends Conditional<string, unknown, infer Elements> ? ExtractFieldsFromArray<Elements> : never;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Extracts conditional fields from an array of elements.
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```typescript
|
|
91
|
+
* type Elements = readonly [
|
|
92
|
+
* TextField<"name">,
|
|
93
|
+
* Conditional<"type", "business", readonly [TextField<"company">]>
|
|
94
|
+
* ];
|
|
95
|
+
* type Fields = ExtractConditionalFieldsFromArray<Elements>;
|
|
96
|
+
* // TextField<"company">
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
export declare type ExtractConditionalFieldsFromArray<Elements> = Elements extends readonly [infer First, ...infer Rest] ? ExtractConditionalFields<First> | ExtractConditionalFieldsFromArray<Rest> : never;
|
|
100
|
+
|
|
66
101
|
/**
|
|
67
102
|
* Extracts all fields from a single element (recursively).
|
|
68
103
|
*
|
|
@@ -82,6 +117,38 @@ infer First,
|
|
|
82
117
|
...infer Rest
|
|
83
118
|
] ? ExtractFields<First> | ExtractFieldsFromArray<Rest> : never;
|
|
84
119
|
|
|
120
|
+
/**
|
|
121
|
+
* Extracts fields that are NOT inside conditionals.
|
|
122
|
+
* These fields are always visible and should be required in the inferred schema.
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```typescript
|
|
126
|
+
* // Given a form with conditional and non-conditional fields:
|
|
127
|
+
* const form = formspec(
|
|
128
|
+
* field.text("name"), // non-conditional
|
|
129
|
+
* field.number("age"), // non-conditional
|
|
130
|
+
* when(is("type", "business"),
|
|
131
|
+
* field.text("company"), // conditional (skipped)
|
|
132
|
+
* ),
|
|
133
|
+
* );
|
|
134
|
+
*
|
|
135
|
+
* // ExtractNonConditionalFields extracts: TextField<"name"> | NumberField<"age">
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
export declare type ExtractNonConditionalFields<E> = E extends AnyField ? E : E extends Group<infer Elements> ? ExtractNonConditionalFieldsFromArray<Elements> : E extends Conditional<string, unknown, infer _Elements> ? never : never;
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Extracts non-conditional fields from an array of elements.
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```typescript
|
|
145
|
+
* type Elements = readonly [TextField<"name">, NumberField<"age">];
|
|
146
|
+
* type Fields = ExtractNonConditionalFieldsFromArray<Elements>;
|
|
147
|
+
* // TextField<"name"> | NumberField<"age">
|
|
148
|
+
* ```
|
|
149
|
+
*/
|
|
150
|
+
export declare type ExtractNonConditionalFieldsFromArray<Elements> = Elements extends readonly [infer First, ...infer Rest] ? ExtractNonConditionalFields<First> | ExtractNonConditionalFieldsFromArray<Rest> : never;
|
|
151
|
+
|
|
85
152
|
/**
|
|
86
153
|
* Field builder namespace containing functions to create each field type.
|
|
87
154
|
*
|
|
@@ -254,6 +321,27 @@ export declare const field: {
|
|
|
254
321
|
objectWithConfig: <const N extends string, const Properties extends readonly FormElement[]>(name: N, config: Omit<ObjectField<N, Properties>, "_type" | "_field" | "name" | "properties">, ...properties: Properties) => ObjectField<N, Properties>;
|
|
255
322
|
};
|
|
256
323
|
|
|
324
|
+
/**
|
|
325
|
+
* Utility type that flattens intersection types into a single object type.
|
|
326
|
+
*
|
|
327
|
+
* This improves TypeScript's display of inferred types and ensures
|
|
328
|
+
* structural equality checks work correctly.
|
|
329
|
+
*
|
|
330
|
+
* @example
|
|
331
|
+
* ```typescript
|
|
332
|
+
* // Without FlattenIntersection:
|
|
333
|
+
* type Messy = { a: string } & { b: number };
|
|
334
|
+
* // Displays as: { a: string } & { b: number }
|
|
335
|
+
*
|
|
336
|
+
* // With FlattenIntersection:
|
|
337
|
+
* type Clean = FlattenIntersection<{ a: string } & { b: number }>;
|
|
338
|
+
* // Displays as: { a: string; b: number }
|
|
339
|
+
* ```
|
|
340
|
+
*/
|
|
341
|
+
export declare type FlattenIntersection<T> = {
|
|
342
|
+
[K in keyof T]: T[K];
|
|
343
|
+
} & {};
|
|
344
|
+
|
|
257
345
|
/**
|
|
258
346
|
* Creates a complete form specification.
|
|
259
347
|
*
|
|
@@ -394,6 +482,8 @@ export declare type InferFormSchema<F extends FormSpec<readonly FormElement[]>>
|
|
|
394
482
|
* This is the main inference type that converts a form structure
|
|
395
483
|
* into its corresponding TypeScript schema type.
|
|
396
484
|
*
|
|
485
|
+
* Non-conditional fields are required, conditional fields are optional.
|
|
486
|
+
*
|
|
397
487
|
* @example
|
|
398
488
|
* ```typescript
|
|
399
489
|
* const form = formspec(
|
|
@@ -404,9 +494,17 @@ export declare type InferFormSchema<F extends FormSpec<readonly FormElement[]>>
|
|
|
404
494
|
*
|
|
405
495
|
* type Schema = InferSchema<typeof form.elements>;
|
|
406
496
|
* // { name: string; age: number; status: "active" | "inactive" }
|
|
497
|
+
*
|
|
498
|
+
* // Conditional fields become optional:
|
|
499
|
+
* const formWithConditional = formspec(
|
|
500
|
+
* field.enum("type", ["a", "b"] as const),
|
|
501
|
+
* when(is("type", "a"), field.text("aField")),
|
|
502
|
+
* );
|
|
503
|
+
* type ConditionalSchema = InferSchema<typeof formWithConditional.elements>;
|
|
504
|
+
* // { type: "a" | "b"; aField?: string }
|
|
407
505
|
* ```
|
|
408
506
|
*/
|
|
409
|
-
export declare type InferSchema<Elements extends readonly FormElement[]> = BuildSchema<
|
|
507
|
+
export declare type InferSchema<Elements extends readonly FormElement[]> = FlattenIntersection<BuildSchema<ExtractNonConditionalFieldsFromArray<Elements>> & Partial<BuildSchema<ExtractConditionalFieldsFromArray<Elements>>>>;
|
|
410
508
|
|
|
411
509
|
/**
|
|
412
510
|
* Creates an equality predicate that checks if a field equals a specific value.
|
package/dist/index.d.ts
CHANGED
|
@@ -34,6 +34,6 @@ export { group, when, formspec, formspecWithValidation } from "./structure.js";
|
|
|
34
34
|
export type { FormSpecOptions } from "./structure.js";
|
|
35
35
|
export { validateForm, logValidationIssues } from "./validation.js";
|
|
36
36
|
export type { ValidationSeverity, ValidationIssue, ValidationResult, } from "./validation.js";
|
|
37
|
-
export type { InferFieldValue, ExtractFields, ExtractFieldsFromArray, BuildSchema, InferSchema, InferFormSchema, } from "./inference.js";
|
|
37
|
+
export type { InferFieldValue, ExtractFields, ExtractFieldsFromArray, ExtractNonConditionalFields, ExtractNonConditionalFieldsFromArray, ExtractConditionalFields, ExtractConditionalFieldsFromArray, BuildSchema, FlattenIntersection, InferSchema, InferFormSchema, } from "./inference.js";
|
|
38
38
|
export type { EnumOption, EnumOptionValue } from "@formspec/core";
|
|
39
39
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAGH,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGnC,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AAGpC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC/E,YAAY,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGtD,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACpE,YAAY,EACV,kBAAkB,EAClB,eAAe,EACf,gBAAgB,GACjB,MAAM,iBAAiB,CAAC;AAGzB,YAAY,EACV,eAAe,EACf,aAAa,EACb,sBAAsB,EACtB,WAAW,EACX,WAAW,EACX,eAAe,GAChB,MAAM,gBAAgB,CAAC;AAGxB,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAGH,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGnC,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AAGpC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC/E,YAAY,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGtD,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACpE,YAAY,EACV,kBAAkB,EAClB,eAAe,EACf,gBAAgB,GACjB,MAAM,iBAAiB,CAAC;AAGzB,YAAY,EACV,eAAe,EACf,aAAa,EACb,sBAAsB,EACtB,2BAA2B,EAC3B,oCAAoC,EACpC,wBAAwB,EACxB,iCAAiC,EACjC,WAAW,EACX,mBAAmB,EACnB,WAAW,EACX,eAAe,GAChB,MAAM,gBAAgB,CAAC;AAGxB,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/inference.d.ts
CHANGED
|
@@ -49,6 +49,69 @@ export type ExtractFieldsFromArray<Elements> = Elements extends readonly [
|
|
|
49
49
|
infer First,
|
|
50
50
|
...infer Rest
|
|
51
51
|
] ? ExtractFields<First> | ExtractFieldsFromArray<Rest> : never;
|
|
52
|
+
/**
|
|
53
|
+
* Extracts fields that are NOT inside conditionals.
|
|
54
|
+
* These fields are always visible and should be required in the inferred schema.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* // Given a form with conditional and non-conditional fields:
|
|
59
|
+
* const form = formspec(
|
|
60
|
+
* field.text("name"), // non-conditional
|
|
61
|
+
* field.number("age"), // non-conditional
|
|
62
|
+
* when(is("type", "business"),
|
|
63
|
+
* field.text("company"), // conditional (skipped)
|
|
64
|
+
* ),
|
|
65
|
+
* );
|
|
66
|
+
*
|
|
67
|
+
* // ExtractNonConditionalFields extracts: TextField<"name"> | NumberField<"age">
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export type ExtractNonConditionalFields<E> = E extends AnyField ? E : E extends Group<infer Elements> ? ExtractNonConditionalFieldsFromArray<Elements> : E extends Conditional<string, unknown, infer _Elements> ? never : never;
|
|
71
|
+
/**
|
|
72
|
+
* Extracts non-conditional fields from an array of elements.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* type Elements = readonly [TextField<"name">, NumberField<"age">];
|
|
77
|
+
* type Fields = ExtractNonConditionalFieldsFromArray<Elements>;
|
|
78
|
+
* // TextField<"name"> | NumberField<"age">
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export type ExtractNonConditionalFieldsFromArray<Elements> = Elements extends readonly [infer First, ...infer Rest] ? ExtractNonConditionalFields<First> | ExtractNonConditionalFieldsFromArray<Rest> : never;
|
|
82
|
+
/**
|
|
83
|
+
* Extracts fields that ARE inside conditionals.
|
|
84
|
+
* These fields may or may not be visible and should be optional in the inferred schema.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* // Given a form with conditional fields:
|
|
89
|
+
* const form = formspec(
|
|
90
|
+
* field.text("name"), // non-conditional (skipped)
|
|
91
|
+
* when(is("type", "business"),
|
|
92
|
+
* field.text("company"), // conditional (extracted)
|
|
93
|
+
* field.text("taxId"), // conditional (extracted)
|
|
94
|
+
* ),
|
|
95
|
+
* );
|
|
96
|
+
*
|
|
97
|
+
* // ExtractConditionalFields extracts: TextField<"company"> | TextField<"taxId">
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
export type ExtractConditionalFields<E> = E extends AnyField ? never : E extends Group<infer Elements> ? ExtractConditionalFieldsFromArray<Elements> : E extends Conditional<string, unknown, infer Elements> ? ExtractFieldsFromArray<Elements> : never;
|
|
101
|
+
/**
|
|
102
|
+
* Extracts conditional fields from an array of elements.
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```typescript
|
|
106
|
+
* type Elements = readonly [
|
|
107
|
+
* TextField<"name">,
|
|
108
|
+
* Conditional<"type", "business", readonly [TextField<"company">]>
|
|
109
|
+
* ];
|
|
110
|
+
* type Fields = ExtractConditionalFieldsFromArray<Elements>;
|
|
111
|
+
* // TextField<"company">
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
export type ExtractConditionalFieldsFromArray<Elements> = Elements extends readonly [infer First, ...infer Rest] ? ExtractConditionalFields<First> | ExtractConditionalFieldsFromArray<Rest> : never;
|
|
52
115
|
/**
|
|
53
116
|
* Builds a schema type from extracted fields.
|
|
54
117
|
*
|
|
@@ -59,12 +122,34 @@ export type BuildSchema<Fields> = {
|
|
|
59
122
|
name: infer N extends string;
|
|
60
123
|
} ? N : never]: F extends AnyField ? InferFieldValue<F> : never;
|
|
61
124
|
};
|
|
125
|
+
/**
|
|
126
|
+
* Utility type that flattens intersection types into a single object type.
|
|
127
|
+
*
|
|
128
|
+
* This improves TypeScript's display of inferred types and ensures
|
|
129
|
+
* structural equality checks work correctly.
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```typescript
|
|
133
|
+
* // Without FlattenIntersection:
|
|
134
|
+
* type Messy = { a: string } & { b: number };
|
|
135
|
+
* // Displays as: { a: string } & { b: number }
|
|
136
|
+
*
|
|
137
|
+
* // With FlattenIntersection:
|
|
138
|
+
* type Clean = FlattenIntersection<{ a: string } & { b: number }>;
|
|
139
|
+
* // Displays as: { a: string; b: number }
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
export type FlattenIntersection<T> = {
|
|
143
|
+
[K in keyof T]: T[K];
|
|
144
|
+
} & {};
|
|
62
145
|
/**
|
|
63
146
|
* Infers the complete schema type from a form's elements.
|
|
64
147
|
*
|
|
65
148
|
* This is the main inference type that converts a form structure
|
|
66
149
|
* into its corresponding TypeScript schema type.
|
|
67
150
|
*
|
|
151
|
+
* Non-conditional fields are required, conditional fields are optional.
|
|
152
|
+
*
|
|
68
153
|
* @example
|
|
69
154
|
* ```typescript
|
|
70
155
|
* const form = formspec(
|
|
@@ -75,9 +160,17 @@ export type BuildSchema<Fields> = {
|
|
|
75
160
|
*
|
|
76
161
|
* type Schema = InferSchema<typeof form.elements>;
|
|
77
162
|
* // { name: string; age: number; status: "active" | "inactive" }
|
|
163
|
+
*
|
|
164
|
+
* // Conditional fields become optional:
|
|
165
|
+
* const formWithConditional = formspec(
|
|
166
|
+
* field.enum("type", ["a", "b"] as const),
|
|
167
|
+
* when(is("type", "a"), field.text("aField")),
|
|
168
|
+
* );
|
|
169
|
+
* type ConditionalSchema = InferSchema<typeof formWithConditional.elements>;
|
|
170
|
+
* // { type: "a" | "b"; aField?: string }
|
|
78
171
|
* ```
|
|
79
172
|
*/
|
|
80
|
-
export type InferSchema<Elements extends readonly FormElement[]> = BuildSchema<
|
|
173
|
+
export type InferSchema<Elements extends readonly FormElement[]> = FlattenIntersection<BuildSchema<ExtractNonConditionalFieldsFromArray<Elements>> & Partial<BuildSchema<ExtractConditionalFieldsFromArray<Elements>>>>;
|
|
81
174
|
/**
|
|
82
175
|
* Infers the schema type from a FormSpec.
|
|
83
176
|
*
|
package/dist/inference.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inference.d.ts","sourceRoot":"","sources":["../src/inference.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,WAAW,EACX,YAAY,EACZ,eAAe,EACf,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EAClB,UAAU,EACV,WAAW,EACX,QAAQ,EACR,KAAK,EACL,WAAW,EACX,WAAW,EACX,QAAQ,EACR,mBAAmB,EACpB,MAAM,gBAAgB,CAAC;AAExB;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI,CAAC,SAAS,SAAS,CAAC,MAAM,CAAC,GACxD,MAAM,GACN,CAAC,SAAS,WAAW,CAAC,MAAM,CAAC,GAC3B,MAAM,GACN,CAAC,SAAS,YAAY,CAAC,MAAM,CAAC,GAC5B,OAAO,GACP,CAAC,SAAS,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,SAAS,SAAS,eAAe,EAAE,CAAC,GAC3E,CAAC,SAAS,SAAS,UAAU,EAAE,GAC7B,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GACf,CAAC,SAAS,SAAS,MAAM,EAAE,GACzB,CAAC,CAAC,MAAM,CAAC,GACT,KAAK,GACT,CAAC,SAAS,gBAAgB,CAAC,MAAM,EAAE,MAAM,MAAM,CAAC,GAC9C,mBAAmB,CAAC,MAAM,CAAC,GAC3B,CAAC,SAAS,kBAAkB,CAAC,MAAM,CAAC,GAClC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACvB,CAAC,SAAS,UAAU,CAAC,MAAM,EAAE,MAAM,KAAK,SAAS,SAAS,WAAW,EAAE,CAAC,GACtE,WAAW,CAAC,KAAK,CAAC,EAAE,GACpB,CAAC,SAAS,WAAW,CAAC,MAAM,EAAE,MAAM,UAAU,SAAS,SAAS,WAAW,EAAE,CAAC,GAC5E,WAAW,CAAC,UAAU,CAAC,GACvB,KAAK,CAAC;AAExB;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI,CAAC,SAAS,QAAQ,GAC7C,CAAC,GACD,CAAC,SAAS,KAAK,CAAC,MAAM,QAAQ,CAAC,GAC7B,sBAAsB,CAAC,QAAQ,CAAC,GAChC,CAAC,SAAS,WAAW,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC,GACpD,sBAAsB,CAAC,QAAQ,CAAC,GAChC,KAAK,CAAC;AAEd;;;;GAIG;AACH,MAAM,MAAM,sBAAsB,CAAC,QAAQ,IAAI,QAAQ,SAAS,SAAS;IACvE,MAAM,KAAK;IACX,GAAG,MAAM,IAAI;CACd,GACG,aAAa,CAAC,KAAK,CAAC,GAAG,sBAAsB,CAAC,IAAI,CAAC,GACnD,KAAK,CAAC;AAEV;;;;GAIG;AACH,MAAM,MAAM,WAAW,CAAC,MAAM,IAAI;KAC/B,CAAC,IAAI,MAAM,IAAI,CAAC,SAAS;QAAE,IAAI,EAAE,MAAM,CAAC,SAAS,MAAM,CAAA;KAAE,GACtD,CAAC,GACD,KAAK,GAAG,CAAC,SAAS,QAAQ,GAAG,eAAe,CAAC,CAAC,CAAC,GAAG,KAAK;CAC5D,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"inference.d.ts","sourceRoot":"","sources":["../src/inference.ts"],"names":[],"mappings":"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"}
|