@@ -41,7 +41,35 @@ function foldleft (xs: Type[]) {
41
41
}
42
42
}
43
43
44
- export function fold ( a : Type , b : Type ) {
44
+ function foldobject (
45
+ a : Exclude < Type [ "object" ] , undefined > ,
46
+ b : Exclude < Type [ "object" ] , undefined > ,
47
+ maybe : Record < string , true > ,
48
+ ) {
49
+ const object = { }
50
+
51
+ for ( const key in a ) {
52
+ if ( key in b ) {
53
+ object [ key ] = fold ( a [ key ] , b [ key ] )
54
+ } else {
55
+ object [ key ] = a [ key ]
56
+ maybe [ key ] = true
57
+ }
58
+ }
59
+
60
+ for ( const key in b ) {
61
+ if ( key in a ) {
62
+ // do nothing
63
+ } else {
64
+ object [ key ] = b [ key ]
65
+ maybe [ key ] = true
66
+ }
67
+ }
68
+
69
+ return { object, maybe }
70
+ }
71
+
72
+ export function fold ( a : Type , b : Type ) : Type {
45
73
if ( a . never ) return { ...b , count : a . count + b . count }
46
74
if ( b . never ) return { ...a , count : a . count + b . count }
47
75
if ( a . scalar && b . scalar && a . scalar === b . scalar ) {
@@ -65,31 +93,20 @@ export function fold (a: Type, b: Type) {
65
93
}
66
94
67
95
if ( a . object && b . object ) {
68
- if ( a . discriminant ?. value === b . discriminant ?. value ) {
69
- const type = {
70
- object : { } as Record < string , Type > ,
71
- maybe : { ...a . maybe , ...b . maybe } as Record < string , true > ,
96
+ if ( a . discriminant && b . discriminant && a . discriminant . value === b . discriminant . value ) {
97
+ return {
98
+ ...foldobject ( a . object , b . object , { ...a . maybe , ...b . maybe } ) ,
72
99
discriminant : a . discriminant ,
73
100
count : a . count + b . count
74
- } satisfies Type
75
-
76
- for ( const key in a . object ) {
77
- if ( key in b . object ) {
78
- type . object [ key ] = fold ( a . object [ key ] , b . object [ key ] )
79
- } else {
80
- type . object [ key ] = a . object [ key ]
81
- type . maybe [ key ] = true
82
- }
83
101
}
84
- for ( const key in b . object ) {
85
- if ( key in a . object ) {
86
- // do nothing
87
- } else {
88
- type . object [ key ] = b . object [ key ]
89
- type . maybe [ key ] = true
90
- }
102
+ }
103
+
104
+ if ( ! a . discriminant && ! b . discriminant ) {
105
+ return {
106
+ ... foldobject ( a . object , b . object , { ... a . maybe , ... b . maybe } ) ,
107
+ discriminant : undefined ,
108
+ count : a . count + b . count
91
109
}
92
- return type
93
110
}
94
111
}
95
112
@@ -141,6 +158,7 @@ export function gettype (
141
158
for ( const key in json ) {
142
159
const innerPath = `${ path } .${ key } `
143
160
if ( omitPaths . includes ( innerPath ) ) continue
161
+
144
162
keyType = fold ( keyType , gettype ( key , `${ path } |keys` , literalPaths , discriminantPaths , recordPaths , omitPaths ) )
145
163
valueType = fold ( valueType , gettype ( json [ key ] , `${ path } []` , literalPaths , discriminantPaths , recordPaths , omitPaths ) )
146
164
}
@@ -160,21 +178,23 @@ export function gettype (
160
178
if ( omitPaths . includes ( innerPath ) ) continue
161
179
162
180
const ft = gettype ( json [ key ] , innerPath , literalPaths , discriminantPaths , recordPaths , omitPaths )
163
- object [ key ] = ft
164
- if ( ft . literal && discriminantPaths . includes ( `${ path } .${ key } ` ) ) {
181
+ if ( ft . literal && discriminantPaths . includes ( innerPath ) ) {
165
182
discriminant = ft . literal
166
183
}
184
+
185
+ object [ key ] = ft
167
186
}
187
+
168
188
return {
169
189
object,
170
190
maybe : { } ,
171
- ... ( discriminant ? { discriminant } : { } ) ,
191
+ discriminant,
172
192
count : 1
173
193
}
174
194
}
175
195
176
196
if ( literalPaths . includes ( path ) ) return { literal : { value : json } , count : 1 }
177
- return { scalar : typeof json , count : 1 } satisfies Type
197
+ return { scalar : typeof json , count : 1 }
178
198
}
179
199
180
200
function comment ( type : Type , count = false ) {
@@ -187,6 +207,7 @@ export function print (type: Type, indent = '', count = false): string {
187
207
if ( type . literal ) return `${ JSON . stringify ( type . literal . value ) } ${ comment ( type , count ) } `
188
208
if ( type . scalar ) return `${ type . scalar } ${ comment ( type , count ) } `
189
209
if ( type . array ) {
210
+ if ( type . array . never ) return `[]${ comment ( type , count ) } `
190
211
if ( type . array . sum ) return `(${ print ( type . array , indent , count ) } )[]`
191
212
return `${ print ( type . array , indent , count ) } []`
192
213
}
0 commit comments