@@ -123,13 +123,12 @@ export class ModelClassVisitor extends AbstractFileVisitor {
123
123
hostFilename = ''
124
124
) : ts . ObjectLiteralExpression {
125
125
const isRequired = ! node . questionToken ;
126
-
127
126
let properties = [
128
127
...existingProperties ,
129
128
! hasPropertyKey ( 'required' , existingProperties ) &&
130
129
ts . createPropertyAssignment ( 'required' , ts . createLiteral ( isRequired ) ) ,
131
- this . createTypePropertyAssignment (
132
- node ,
130
+ ... this . createTypePropertyAssignments (
131
+ node . type ,
133
132
typeChecker ,
134
133
existingProperties ,
135
134
hostFilename
@@ -151,64 +150,107 @@ export class ModelClassVisitor extends AbstractFileVisitor {
151
150
return objectLiteral ;
152
151
}
153
152
154
- createTypePropertyAssignment (
155
- node : ts . PropertyDeclaration | ts . PropertySignature ,
153
+ /**
154
+ * The function returns an array with 0, 1 or 2 PropertyAssignments.
155
+ * Possible keys:
156
+ * - 'type'
157
+ * - 'nullable'
158
+ */
159
+ private createTypePropertyAssignments (
160
+ node : ts . TypeNode ,
156
161
typeChecker : ts . TypeChecker ,
157
162
existingProperties : ts . NodeArray < ts . PropertyAssignment > ,
158
163
hostFilename : string
159
- ) {
164
+ ) : ts . PropertyAssignment [ ] {
160
165
const key = 'type' ;
161
166
if ( hasPropertyKey ( key , existingProperties ) ) {
162
- return undefined ;
163
- }
164
- const type = typeChecker . getTypeAtLocation ( node ) ;
165
- if ( ! type ) {
166
- return undefined ;
167
+ return [ ] ;
167
168
}
168
- if ( node . type && ts . isTypeLiteralNode ( node . type ) ) {
169
- const propertyAssignments = Array . from ( node . type . members || [ ] ) . map (
170
- ( member ) => {
171
- const literalExpr = this . createDecoratorObjectLiteralExpr (
172
- member as ts . PropertySignature ,
169
+ if ( node ) {
170
+ if ( ts . isTypeLiteralNode ( node ) ) {
171
+ const propertyAssignments = Array . from ( node . members || [ ] ) . map (
172
+ ( member ) => {
173
+ const literalExpr = this . createDecoratorObjectLiteralExpr (
174
+ member as ts . PropertySignature ,
175
+ typeChecker ,
176
+ existingProperties ,
177
+ { } ,
178
+ hostFilename
179
+ ) ;
180
+ return ts . createPropertyAssignment (
181
+ ts . createIdentifier ( member . name . getText ( ) ) ,
182
+ literalExpr
183
+ ) ;
184
+ }
185
+ ) ;
186
+ return [
187
+ ts . createPropertyAssignment (
188
+ key ,
189
+ ts . createArrowFunction (
190
+ undefined ,
191
+ undefined ,
192
+ [ ] ,
193
+ undefined ,
194
+ undefined ,
195
+ ts . createParen ( ts . createObjectLiteral ( propertyAssignments ) )
196
+ )
197
+ )
198
+ ] ;
199
+ } else if ( ts . isUnionTypeNode ( node ) ) {
200
+ const nullableType = node . types . find (
201
+ ( type ) => type . kind === ts . SyntaxKind . NullKeyword
202
+ ) ;
203
+ const isNullable = ! ! nullableType ;
204
+ const remainingTypes = node . types . filter (
205
+ ( item ) => item !== nullableType
206
+ ) ;
207
+
208
+ // When we have more than 1 type left, we could use oneOf
209
+ if ( remainingTypes . length === 1 ) {
210
+ const remainingTypesProperties = this . createTypePropertyAssignments (
211
+ remainingTypes [ 0 ] ,
173
212
typeChecker ,
174
213
existingProperties ,
175
- { } ,
176
214
hostFilename
177
215
) ;
178
- return ts . createPropertyAssignment (
179
- ts . createIdentifier ( member . name . getText ( ) ) ,
180
- literalExpr
216
+
217
+ const resultArray = new Array < ts . PropertyAssignment > (
218
+ ... remainingTypesProperties
181
219
) ;
220
+ if ( isNullable ) {
221
+ const nullablePropertyAssignment = ts . createPropertyAssignment (
222
+ 'nullable' ,
223
+ ts . createTrue ( )
224
+ ) ;
225
+ resultArray . push ( nullablePropertyAssignment ) ;
226
+ }
227
+ return resultArray ;
182
228
}
183
- ) ;
184
- return ts . createPropertyAssignment (
229
+ }
230
+ }
231
+
232
+ const type = typeChecker . getTypeAtLocation ( node ) ;
233
+ if ( ! type ) {
234
+ return [ ] ;
235
+ }
236
+ let typeReference = getTypeReferenceAsString ( type , typeChecker ) ;
237
+ if ( ! typeReference ) {
238
+ return [ ] ;
239
+ }
240
+ typeReference = replaceImportPath ( typeReference , hostFilename ) ;
241
+ return [
242
+ ts . createPropertyAssignment (
185
243
key ,
186
244
ts . createArrowFunction (
187
245
undefined ,
188
246
undefined ,
189
247
[ ] ,
190
248
undefined ,
191
249
undefined ,
192
- ts . createParen ( ts . createObjectLiteral ( propertyAssignments ) )
250
+ ts . createIdentifier ( typeReference )
193
251
)
194
- ) ;
195
- }
196
- let typeReference = getTypeReferenceAsString ( type , typeChecker ) ;
197
- if ( ! typeReference ) {
198
- return undefined ;
199
- }
200
- typeReference = replaceImportPath ( typeReference , hostFilename ) ;
201
- return ts . createPropertyAssignment (
202
- key ,
203
- ts . createArrowFunction (
204
- undefined ,
205
- undefined ,
206
- [ ] ,
207
- undefined ,
208
- undefined ,
209
- ts . createIdentifier ( typeReference )
210
252
)
211
- ) ;
253
+ ] ;
212
254
}
213
255
214
256
createEnumPropertyAssignment (
0 commit comments