11import { ASTConverter , ASTResultKind , ASTTransform , ASTResultToObject , ReferenceKind } from '../types'
2- import type ts from 'typescript'
2+ import ts from 'typescript'
33import { copySyntheticComments } from '../../utils'
44
55const propDecoratorName = 'Prop'
@@ -10,24 +10,48 @@ export const convertProp: ASTConverter<ts.PropertyDeclaration> = (node, options)
1010 }
1111 const decorator = node . decorators . find ( ( el ) => ( el . expression as ts . CallExpression ) . expression . getText ( ) === propDecoratorName )
1212 if ( decorator ) {
13+ const propType = 'PropType'
1314 const tsModule = options . typescript
15+ const type = node . type ?. kind
1416 const decoratorArguments = ( decorator . expression as ts . CallExpression ) . arguments
15- if ( decoratorArguments . length > 0 ) {
17+ const hasKnowableType = type !== undefined && type !== ts . SyntaxKind . AnyKeyword && type !== ts . SyntaxKind . UndefinedKeyword && type !== ts . SyntaxKind . UnknownKeyword
18+ let addedPropKey = false
19+
20+ if ( decoratorArguments . length > 0 || hasKnowableType ) {
1621 const propName = node . name . getText ( )
17- const propArguments = decoratorArguments [ 0 ]
22+ const propArguments = decoratorArguments [ 0 ] as ts . ObjectLiteralExpression
23+ const props = propArguments . properties
24+ . reduce ( ( accumulator , property ) => {
25+ if ( property . kind === ts . SyntaxKind . PropertyAssignment ) {
26+ if ( node . type && property . name . getText ( ) === 'type' ) {
27+ const typeReference = ts . createTypeReferenceNode ( propType , [ node . type ] )
28+ property . initializer = tsModule . createAsExpression ( property . initializer , typeReference )
29+ addedPropKey = true
30+ }
31+
32+ accumulator . push ( property )
33+ }
34+
35+ return accumulator
36+ } , [ ] as ts . ObjectLiteralElementLike [ ] )
37+
38+ const args = tsModule . createObjectLiteral ( props )
1839
1940 return {
2041 tag : 'Prop' ,
21- kind : ASTResultKind . OBJECT ,
22- imports : [ ] ,
42+ kind : ASTResultKind . COMPOSITION ,
43+ imports : addedPropKey ? [ {
44+ named : [ propType ] ,
45+ external : ( options . compatible ) ? '@vue/composition-api' : 'vue'
46+ } ] : [ ] ,
2347 reference : ReferenceKind . PROPS ,
2448 attributes : [ propName ] ,
2549 nodes : [
2650 copySyntheticComments (
2751 tsModule ,
2852 tsModule . createPropertyAssignment (
2953 tsModule . createIdentifier ( propName ) ,
30- propArguments
54+ args
3155 ) ,
3256 node
3357 )
@@ -38,18 +62,20 @@ export const convertProp: ASTConverter<ts.PropertyDeclaration> = (node, options)
3862
3963 return false
4064}
65+
4166export const mergeProps : ASTTransform = ( astResults , options ) => {
4267 const tsModule = options . typescript
4368 const propTags = [ 'Prop' , 'Model' ]
4469
4570 const propASTResults = astResults . filter ( ( el ) => propTags . includes ( el . tag ) )
4671 const otherASTResults = astResults . filter ( ( el ) => ! propTags . includes ( el . tag ) )
4772 const modelASTResult = astResults . find ( ( el ) => el . tag === 'Model' )
73+ const imports = propASTResults . find ( el => el . imports . length > 0 ) ?. imports || [ ]
4874
4975 const mergeASTResult : ASTResultToObject = {
5076 tag : 'Prop' ,
5177 kind : ASTResultKind . OBJECT ,
52- imports : [ ] ,
78+ imports,
5379 reference : ReferenceKind . PROPS ,
5480 attributes : propASTResults . map ( ( el ) => el . attributes ) . reduce ( ( array , el ) => array . concat ( el ) , [ ] ) ,
5581 nodes : [
0 commit comments