@@ -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,108 @@ 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
+ */
210
+ if ( remainingTypes . length === 1 ) {
211
+ const remainingTypesProperties = this . createTypePropertyAssignments (
212
+ remainingTypes [ 0 ] ,
173
213
typeChecker ,
174
214
existingProperties ,
175
- { } ,
176
215
hostFilename
177
216
) ;
178
- return ts . createPropertyAssignment (
179
- ts . createIdentifier ( member . name . getText ( ) ) ,
180
- literalExpr
217
+
218
+ const resultArray = new Array < ts . PropertyAssignment > (
219
+ ... remainingTypesProperties
181
220
) ;
221
+ if ( isNullable ) {
222
+ const nullablePropertyAssignment = ts . createPropertyAssignment (
223
+ 'nullable' ,
224
+ ts . createTrue ( )
225
+ ) ;
226
+ resultArray . push ( nullablePropertyAssignment ) ;
227
+ }
228
+ return resultArray ;
182
229
}
183
- ) ;
184
- return ts . createPropertyAssignment (
230
+ }
231
+ }
232
+
233
+ const type = typeChecker . getTypeAtLocation ( node ) ;
234
+ if ( ! type ) {
235
+ return [ ] ;
236
+ }
237
+ let typeReference = getTypeReferenceAsString ( type , typeChecker ) ;
238
+ if ( ! typeReference ) {
239
+ return [ ] ;
240
+ }
241
+ typeReference = replaceImportPath ( typeReference , hostFilename ) ;
242
+ return [
243
+ ts . createPropertyAssignment (
185
244
key ,
186
245
ts . createArrowFunction (
187
246
undefined ,
188
247
undefined ,
189
248
[ ] ,
190
249
undefined ,
191
250
undefined ,
192
- ts . createParen ( ts . createObjectLiteral ( propertyAssignments ) )
251
+ ts . createIdentifier ( typeReference )
193
252
)
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
253
)
211
- ) ;
254
+ ] ;
212
255
}
213
256
214
257
createEnumPropertyAssignment (
0 commit comments