@@ -9,6 +9,7 @@ import ts from "typescript";
99import { TsHelper } from "../../helpers/TsHelper" ;
1010
1111const propDecoratorName = "Prop" ;
12+ let $t : TsHelper ;
1213
1314export const convertProp : ASTConverter < ts . PropertyDeclaration > = ( node , options ) => {
1415 if ( ! node . decorators ) {
@@ -19,28 +20,30 @@ export const convertProp: ASTConverter<ts.PropertyDeclaration> = (node, options)
1920 ) ;
2021 if ( decorator ) {
2122 const propType = "PropType" ;
22- const $t = new TsHelper ( options ) ;
23- const type = node . type ?. kind ;
23+ $t = new TsHelper ( options ) ;
24+ let type = node . type ?. kind ;
2425 const decoratorArguments = ( decorator . expression as ts . CallExpression ) . arguments ;
2526 const hasKnowableType =
2627 type !== undefined &&
2728 type !== ts . SyntaxKind . AnyKeyword &&
2829 type !== ts . SyntaxKind . UndefinedKeyword &&
2930 type !== ts . SyntaxKind . UnknownKeyword ;
30- let addedPropKey = false ;
31+ let addedPropType = false ;
32+ let addTodoComplex = false ;
33+
34+ let props : ts . ObjectLiteralElementLike [ ] = [ ] ;
35+ const propName = node . name . getText ( ) ;
3136
3237 if ( decoratorArguments . length > 0 || hasKnowableType ) {
33- const propName = node . name . getText ( ) ;
3438 const propArguments = decoratorArguments [ 0 ] ;
35- let props : ts . ObjectLiteralElementLike [ ] = [ ] ;
3639 if ( propArguments && $t . module . isObjectLiteralExpression ( propArguments ) ) {
3740 props = propArguments . properties . reduce ( ( accumulator , property ) => {
3841 if ( property . kind === ts . SyntaxKind . PropertyAssignment ) {
3942 let initializer : ts . AsExpression = property . initializer as ts . AsExpression ;
4043 if ( node . type && property . name . getText ( ) === "type" ) {
4144 const typeReference = $t . factory . createTypeReferenceNode ( propType , [ node . type ] ) ;
4245 initializer = $t . factory . createAsExpression ( property . initializer , typeReference ) ;
43- addedPropKey = true ;
46+ addedPropType = true ;
4447 }
4548
4649 const newProperty = $t . factory . createPropertyAssignment ( property . name , initializer ) ;
@@ -49,26 +52,91 @@ export const convertProp: ASTConverter<ts.PropertyDeclaration> = (node, options)
4952
5053 return accumulator ;
5154 } , [ ] as ts . ObjectLiteralElementLike [ ] ) ;
52- }
55+ } else if ( node . type && hasKnowableType ) {
56+ let primType : string | undefined ;
57+
58+ if ( $t . module . isLiteralTypeNode ( node . type ) ) {
59+ type = node . type . literal . kind ;
60+ }
5361
54- const args = $t . factory . createObjectLiteralExpression ( props ) ;
55-
56- return {
57- tag : "Prop" ,
58- kind : ASTResultKind . COMPOSITION ,
59- imports : addedPropKey ? $t . namedImports ( [ propType ] ) : [ ] ,
60- reference : ReferenceKind . PROPS ,
61- attributes : [ propName ] ,
62- nodes : [
63- $t . copySyntheticComments ( $t . factory . createPropertyAssignment ( propName , args ) , node ) ,
64- ] ,
65- } ;
62+ switch ( type ) {
63+ case ts . SyntaxKind . StringLiteral :
64+ addedPropType = true ;
65+ primType = "String" ;
66+ break ;
67+ case ts . SyntaxKind . StringKeyword :
68+ primType = "String" ;
69+ break ;
70+ case ts . SyntaxKind . TrueKeyword :
71+ case ts . SyntaxKind . FalseKeyword :
72+ addedPropType = true ;
73+ primType = "Boolean" ;
74+ break ;
75+ case ts . SyntaxKind . BooleanKeyword :
76+ primType = "Boolean" ;
77+ break ;
78+ case ts . SyntaxKind . NumericLiteral :
79+ addedPropType = true ;
80+ primType = "Number" ;
81+ break ;
82+ case ts . SyntaxKind . NumberKeyword :
83+ primType = "Number" ;
84+ break ;
85+ default :
86+ addTodoComplex = true ;
87+ break ;
88+ }
89+
90+ if ( primType ) {
91+ const vueIdentifier = $t . factory . createIdentifier ( primType ) ;
92+ const tsIdentifier = addedPropType
93+ ? $t . factory . createIdentifier ( node . type . getText ( ) )
94+ : undefined ;
95+ props = [ createPropTypeAssignment ( vueIdentifier , tsIdentifier ) ] ;
96+ }
97+ }
6698 }
99+ const args = $t . factory . createObjectLiteralExpression ( props . length > 0 ? props : undefined ) ;
100+ let propAssignment = $t . factory . createPropertyAssignment ( propName , args ) ;
101+ propAssignment = addTodoComplex
102+ ? $t . addTodoComment (
103+ propAssignment ,
104+ `Too complex to determine primitive type: ${ node . type ! . getText ( ) } ` ,
105+ true
106+ )
107+ : propAssignment ;
108+
109+ return {
110+ tag : "Prop" ,
111+ kind : ASTResultKind . COMPOSITION ,
112+ imports : addedPropType ? $t . namedImports ( [ propType ] ) : [ ] ,
113+ reference : ReferenceKind . PROPS ,
114+ attributes : [ propName ] ,
115+ nodes : [ $t . copySyntheticComments ( propAssignment , node ) ] ,
116+ } ;
67117 }
68118
69119 return false ;
70120} ;
71121
122+ function createPropTypeAssignment (
123+ vueTypeIdentifier : ts . Identifier ,
124+ tsTypeIdentifier ?: ts . Identifier
125+ ) {
126+ const typeId = $t . factory . createIdentifier ( "type" ) ;
127+
128+ if ( ! tsTypeIdentifier ) {
129+ return $t . factory . createPropertyAssignment ( typeId , vueTypeIdentifier ) ;
130+ }
131+
132+ const tsTypeRef = $t . factory . createTypeReferenceNode ( tsTypeIdentifier , undefined ) ;
133+ const propTypeId = $t . factory . createIdentifier ( "PropType" ) ;
134+ const propTypeRef = $t . factory . createTypeReferenceNode ( propTypeId , [ tsTypeRef ] ) ;
135+ const asExpr = $t . factory . createAsExpression ( vueTypeIdentifier , propTypeRef ) ;
136+ const propAssignment = $t . factory . createPropertyAssignment ( typeId , asExpr ) ;
137+ return propAssignment ;
138+ }
139+
72140export const mergeProps : ASTTransform = ( astResults , options ) => {
73141 const $t = new TsHelper ( options ) ;
74142 const propTags = [ "Prop" , "Model" ] ;
0 commit comments