@@ -89,8 +89,11 @@ class TypescriptVisitor {
8989 visitModelFile ( modelFile , parameters ) {
9090 parameters . fileWriter . openFile ( modelFile . getNamespace ( ) + '.ts' ) ;
9191
92+ parameters . fileWriter . writeLine ( 0 , `// Generated code for namespace: ${ modelFile . getNamespace ( ) } ` ) ;
93+
9294 // Compute the types we need to import (based on all the types of the properites
9395 // as well as all the super types) for all the classes in this model file
96+ parameters . fileWriter . writeLine ( 0 , '\n// imports' ) ;
9497 const properties = new Map ( ) ;
9598 modelFile . getAllDeclarations ( )
9699 . filter ( v => ! v . isEnum ( ) )
@@ -101,6 +104,7 @@ class TypescriptVisitor {
101104 if ( ! properties . has ( typeNamespace ) ) {
102105 properties . set ( typeNamespace , new Set ( ) ) ;
103106 }
107+ properties . get ( typeNamespace ) . add ( `I${ typeName } ` ) ;
104108 properties . get ( typeNamespace ) . add ( typeName ) ;
105109 }
106110
@@ -111,6 +115,7 @@ class TypescriptVisitor {
111115 if ( ! properties . has ( typeNamespace ) ) {
112116 properties . set ( typeNamespace , new Set ( ) ) ;
113117 }
118+ properties . get ( typeNamespace ) . add ( `I${ typeName } ` ) ;
114119 properties . get ( typeNamespace ) . add ( typeName ) ;
115120 }
116121 } ) ;
@@ -126,13 +131,11 @@ class TypescriptVisitor {
126131 }
127132 } ) ;
128133
129- parameters . fileWriter . writeLine ( 0 , '// export namespace ' + modelFile . getNamespace ( ) + '{' ) ;
130-
134+ parameters . fileWriter . writeLine ( 0 , '\n// types' ) ;
131135 modelFile . getAllDeclarations ( ) . forEach ( ( decl ) => {
132136 decl . accept ( this , parameters ) ;
133137 } ) ;
134138
135- parameters . fileWriter . writeLine ( 0 , '// }' ) ;
136139 parameters . fileWriter . closeFile ( ) ;
137140
138141 return null ;
@@ -147,13 +150,13 @@ class TypescriptVisitor {
147150 */
148151 visitEnumDeclaration ( enumDeclaration , parameters ) {
149152
150- parameters . fileWriter . writeLine ( 1 , 'export enum ' + enumDeclaration . getName ( ) + ' {' ) ;
153+ parameters . fileWriter . writeLine ( 0 , 'export enum ' + enumDeclaration . getName ( ) + ' {' ) ;
151154
152155 enumDeclaration . getOwnProperties ( ) . forEach ( ( property ) => {
153156 property . accept ( this , parameters ) ;
154157 } ) ;
155158
156- parameters . fileWriter . writeLine ( 1 , '}' ) ;
159+ parameters . fileWriter . writeLine ( 0 , '}\n ' ) ;
157160 return null ;
158161 }
159162
@@ -166,26 +169,42 @@ class TypescriptVisitor {
166169 */
167170 visitClassDeclaration ( classDeclaration , parameters ) {
168171
169-
170- let isAbstract = '' ;
171- if ( classDeclaration . isAbstract ( ) ) {
172- isAbstract = 'export abstract ' ;
173- } else {
174- isAbstract = 'export ' ;
172+ let superType = ' ' ;
173+ if ( classDeclaration . getSuperType ( ) ) {
174+ superType = ` extends I${ ModelUtil . getShortName ( classDeclaration . getSuperType ( ) ) } ` ;
175175 }
176176
177- let superType = '' ;
177+ parameters . fileWriter . writeLine ( 0 , 'export interface I' + classDeclaration . getName ( ) + superType + '{' ) ;
178+
179+ classDeclaration . getOwnProperties ( ) . forEach ( ( property ) => {
180+ property . accept ( this , parameters ) ;
181+ } ) ;
182+
183+ parameters . fileWriter . writeLine ( 0 , '}\n' ) ;
184+
185+ const exportDecl = classDeclaration . isAbstract ( ) ? 'export abstract' : 'export' ;
186+
178187 if ( classDeclaration . getSuperType ( ) ) {
179- superType = ' extends ' + ModelUtil . getShortName ( classDeclaration . getSuperType ( ) ) ;
188+ superType = ` extends ${ ModelUtil . getShortName ( classDeclaration . getSuperType ( ) ) } ` ;
180189 }
181190
182- parameters . fileWriter . writeLine ( 1 , isAbstract + 'class ' + classDeclaration . getName ( ) + superType + ' {' ) ;
183-
191+ parameters . fileWriter . writeLine ( 0 , `${ exportDecl } class ${ classDeclaration . getName ( ) } ${ superType } implements I${ classDeclaration . getName ( ) } {` ) ;
192+ parameters . fileWriter . writeLine ( 1 , 'public static $class: string' ) ;
193+ parameters . useDefiniteAssignment = true ;
184194 classDeclaration . getOwnProperties ( ) . forEach ( ( property ) => {
185195 property . accept ( this , parameters ) ;
186196 } ) ;
197+ parameters . useDefiniteAssignment = false ;
187198
199+ parameters . fileWriter . writeLine ( 1 , `public constructor(data: I${ classDeclaration . getName ( ) } ) {` ) ;
200+ if ( classDeclaration . getSuperType ( ) ) {
201+ parameters . fileWriter . writeLine ( 2 , 'super(data);' ) ;
202+ }
203+ parameters . fileWriter . writeLine ( 2 , 'Object.assign(this, data);' ) ;
204+ parameters . fileWriter . writeLine ( 2 , `${ classDeclaration . getName ( ) } .$class = '${ classDeclaration . getFullyQualifiedName ( ) } '` ) ;
188205 parameters . fileWriter . writeLine ( 1 , '}' ) ;
206+ parameters . fileWriter . writeLine ( 0 , '}\n' ) ;
207+
189208 return null ;
190209 }
191210
@@ -203,7 +222,12 @@ class TypescriptVisitor {
203222 array = '[]' ;
204223 }
205224
206- parameters . fileWriter . writeLine ( 2 , field . getName ( ) + ': ' + this . toTsType ( field . getType ( ) ) + array + ';' ) ;
225+ const isEnumRef = field . isPrimitive ( ) ? false
226+ : field . getParent ( ) . getModelFile ( ) . getModelManager ( ) . getType ( field . getFullyQualifiedTypeName ( ) ) . isEnum ( ) ;
227+
228+ const assignment = parameters . useDefiniteAssignment ? '!' : '' ;
229+
230+ parameters . fileWriter . writeLine ( 1 , field . getName ( ) + assignment + ': ' + this . toTsType ( field . getType ( ) , ! isEnumRef ) + array + ';' ) ;
207231 return null ;
208232 }
209233
@@ -215,7 +239,7 @@ class TypescriptVisitor {
215239 * @private
216240 */
217241 visitEnumValueDeclaration ( enumValueDeclaration , parameters ) {
218- parameters . fileWriter . writeLine ( 2 , enumValueDeclaration . getName ( ) + ',' ) ;
242+ parameters . fileWriter . writeLine ( 1 , enumValueDeclaration . getName ( ) + ',' ) ;
219243 return null ;
220244 }
221245
@@ -233,19 +257,22 @@ class TypescriptVisitor {
233257 array = '[]' ;
234258 }
235259
236- // we export all relationships by capitalizing them
237- parameters . fileWriter . writeLine ( 2 , relationship . getName ( ) + ': ' + this . toTsType ( relationship . getType ( ) ) + array + ';' ) ;
260+ const assignment = parameters . useDefiniteAssignment ? '!' : '' ;
261+
262+ // we export all relationships
263+ parameters . fileWriter . writeLine ( 1 , relationship . getName ( ) + assignment + ': ' + this . toTsType ( relationship . getType ( ) , true ) + array + ';' ) ;
238264 return null ;
239265 }
240266
241267 /**
242268 * Converts a Concerto type to a Typescript type. Primitive types are converted
243269 * everything else is passed through unchanged.
244270 * @param {string } type - the concerto type
271+ * @param {boolean } useInterface - whether to use an interface type
245272 * @return {string } the corresponding type in Typescript
246273 * @private
247274 */
248- toTsType ( type ) {
275+ toTsType ( type , useInterface ) {
249276 switch ( type ) {
250277 case 'DateTime' :
251278 return 'Date' ;
@@ -260,7 +287,7 @@ class TypescriptVisitor {
260287 case 'Integer' :
261288 return 'number' ;
262289 default :
263- return type ;
290+ return useInterface ? `I ${ type } ` : type ;
264291 }
265292 }
266293}
0 commit comments