@@ -74,7 +74,7 @@ type EnumString<T> = [T] extends [never]
74
74
: null
75
75
76
76
/** true if type is a union of string literals */
77
- type IsEnum < T > = null extends EnumString < Exclude < T , null > > ? false : true
77
+ type IsEnum < T > = null extends EnumString < T > ? false : true
78
78
79
79
/** true only if all types are array types (not tuples) */
80
80
// NOTE relies on the fact that tuples don't have an index at 0.5, but arrays
@@ -88,13 +88,18 @@ type IsElements<T> = false extends IsUnion<T>
88
88
: false
89
89
90
90
/** true if the the type is a values type */
91
- type IsValues < T > = false extends IsUnion < Exclude < T , null > >
92
- ? TypeEquality < keyof Exclude < T , null > , string >
91
+ type IsValues < T > = false extends IsUnion < T > ? TypeEquality < keyof T , string > : false
92
+
93
+ /** true if type is a properties type and Union is false, or type is a discriminator type and Union is true */
94
+ type IsRecord < T , Union extends boolean > = Union extends IsUnion < T >
95
+ ? null extends EnumString < keyof T >
96
+ ? false
97
+ : true
93
98
: false
94
99
95
- /** true if type is a proeprties type and Union is false, or type is a discriminator type and Union is true */
96
- type IsRecord < T , Union extends boolean > = Union extends IsUnion < Exclude < T , null > >
97
- ? null extends EnumString < keyof Exclude < T , null > >
100
+ /** true if type represents an empty record */
101
+ type IsEmptyRecord < T > = [ T ] extends [ Record < string , never > ]
102
+ ? [ T ] extends [ never ]
98
103
? false
99
104
: true
100
105
: false
@@ -131,7 +136,7 @@ export type JTDSchemaType<T, D extends Record<string, unknown> = Record<string,
131
136
? { type : "timestamp" }
132
137
: // enums - only accepts union of string literals
133
138
// TODO we can't actually check that everything in the union was specified
134
- true extends IsEnum < T >
139
+ true extends IsEnum < Exclude < T , null > >
135
140
? { enum : EnumString < Exclude < T , null > > [ ] }
136
141
: // arrays - only accepts arrays, could be array of unions to be resolved later
137
142
true extends IsElements < Exclude < T , null > >
@@ -140,15 +145,20 @@ export type JTDSchemaType<T, D extends Record<string, unknown> = Record<string,
140
145
elements : JTDSchemaType < E , D >
141
146
}
142
147
: never
148
+ : // empty properties
149
+ true extends IsEmptyRecord < Exclude < T , null > >
150
+ ?
151
+ | { properties : Record < string , never > ; optionalProperties ?: Record < string , never > }
152
+ | { optionalProperties : Record < string , never > }
143
153
: // values
144
- true extends IsValues < T >
154
+ true extends IsValues < Exclude < T , null > >
145
155
? T extends Record < string , infer V >
146
156
? {
147
157
values : JTDSchemaType < V , D >
148
158
}
149
159
: never
150
160
: // properties
151
- true extends IsRecord < T , false >
161
+ true extends IsRecord < Exclude < T , null > , false >
152
162
? ( [ RequiredKeys < Exclude < T , null > > ] extends [ never ]
153
163
? {
154
164
properties ?: Record < string , never >
@@ -168,15 +178,15 @@ export type JTDSchemaType<T, D extends Record<string, unknown> = Record<string,
168
178
additionalProperties ?: boolean
169
179
}
170
180
: // discriminator
171
- true extends IsRecord < T , true >
181
+ true extends IsRecord < Exclude < T , null > , true >
172
182
? {
173
183
[ K in keyof Exclude < T , null > ] -?: Exclude < T , null > [ K ] extends string
174
184
? {
175
185
discriminator : K
176
186
mapping : {
177
187
// TODO currently allows descriminator to be present in schema
178
188
[ M in Exclude < T , null > [ K ] ] : JTDSchemaType <
179
- Omit < T extends { [ C in K ] : M } ? T : never , K > ,
189
+ Omit < T extends Record < K , M > ? T : never , K > ,
180
190
D
181
191
>
182
192
}
0 commit comments