@@ -84,8 +84,17 @@ const plugin: (
8484 node . arguments . push ( options ) ;
8585 }
8686
87- node . arguments [ 1 ] = processProps ( comp , options ) || options ;
88- node . arguments [ 1 ] = processEmits ( comp , node . arguments [ 1 ] ) || options ;
87+ let propsGenerics : BabelCore . types . TSType | undefined ;
88+ let emitsGenerics : BabelCore . types . TSType | undefined ;
89+ if ( node . typeParameters && node . typeParameters . params . length > 0 ) {
90+ propsGenerics = node . typeParameters . params [ 0 ] ;
91+ emitsGenerics = node . typeParameters . params [ 1 ] ;
92+ }
93+
94+ node . arguments [ 1 ] =
95+ processProps ( comp , propsGenerics , options ) || options ;
96+ node . arguments [ 1 ] =
97+ processEmits ( comp , emitsGenerics , node . arguments [ 1 ] ) || options ;
8998 } ,
9099 VariableDeclarator ( path ) {
91100 inferComponentName ( path ) ;
@@ -125,6 +134,7 @@ const plugin: (
125134
126135 function processProps (
127136 comp : BabelCore . types . Function ,
137+ generics : BabelCore . types . TSType | undefined ,
128138 options :
129139 | BabelCore . types . ArgumentPlaceholder
130140 | BabelCore . types . SpreadElement
@@ -134,10 +144,18 @@ const plugin: (
134144 if ( ! props ) return ;
135145
136146 if ( props . type === 'AssignmentPattern' ) {
137- ctx ! . propsTypeDecl = getTypeAnnotation ( props . left ) ;
147+ if ( generics ) {
148+ ctx ! . propsTypeDecl = resolveTypeReference ( generics ) ;
149+ } else {
150+ ctx ! . propsTypeDecl = getTypeAnnotation ( props . left ) ;
151+ }
138152 ctx ! . propsRuntimeDefaults = props . right ;
139153 } else {
140- ctx ! . propsTypeDecl = getTypeAnnotation ( props ) ;
154+ if ( generics ) {
155+ ctx ! . propsTypeDecl = resolveTypeReference ( generics ) ;
156+ } else {
157+ ctx ! . propsTypeDecl = getTypeAnnotation ( props ) ;
158+ }
141159 }
142160
143161 if ( ! ctx ! . propsTypeDecl ) return ;
@@ -157,20 +175,26 @@ const plugin: (
157175
158176 function processEmits (
159177 comp : BabelCore . types . Function ,
178+ generics : BabelCore . types . TSType | undefined ,
160179 options :
161180 | BabelCore . types . ArgumentPlaceholder
162181 | BabelCore . types . SpreadElement
163182 | BabelCore . types . Expression
164183 ) {
184+ let emitType : BabelCore . types . Node | undefined ;
185+ if ( generics ) {
186+ emitType = resolveTypeReference ( generics ) ;
187+ }
188+
165189 const setupCtx = comp . params [ 1 ] && getTypeAnnotation ( comp . params [ 1 ] ) ;
166190 if (
167- ! setupCtx ||
168- ! t . isTSTypeReference ( setupCtx ) ||
169- ! t . isIdentifier ( setupCtx . typeName , { name : 'SetupContext' } )
170- )
171- return ;
172-
173- const emitType = setupCtx . typeParameters ?. params [ 0 ] ;
191+ ! emitType &&
192+ setupCtx &&
193+ t . isTSTypeReference ( setupCtx ) &&
194+ t . isIdentifier ( setupCtx . typeName , { name : 'SetupContext' } )
195+ ) {
196+ emitType = setupCtx . typeParameters ?. params [ 0 ] ;
197+ }
174198 if ( ! emitType ) return ;
175199
176200 ctx ! . emitsTypeDecl = emitType ;
@@ -185,8 +209,84 @@ const plugin: (
185209 t . objectProperty ( t . identifier ( 'emits' ) , ast )
186210 ) ;
187211 }
188- } ) ;
189212
213+ function resolveTypeReference ( typeNode : BabelCore . types . TSType ) {
214+ if ( ! ctx ) return ;
215+
216+ if ( t . isTSTypeReference ( typeNode ) ) {
217+ const typeName = getTypeReferenceName ( typeNode ) ;
218+ if ( typeName ) {
219+ const typeDeclaration = findTypeDeclaration ( typeName ) ;
220+ if ( typeDeclaration ) {
221+ return typeDeclaration ;
222+ }
223+ }
224+ }
225+
226+ return ;
227+ }
228+
229+ function getTypeReferenceName ( typeRef : BabelCore . types . TSTypeReference ) {
230+ if ( t . isIdentifier ( typeRef . typeName ) ) {
231+ return typeRef . typeName . name ;
232+ } else if ( t . isTSQualifiedName ( typeRef . typeName ) ) {
233+ const parts : string [ ] = [ ] ;
234+ let current : BabelCore . types . TSEntityName = typeRef . typeName ;
235+
236+ while ( t . isTSQualifiedName ( current ) ) {
237+ if ( t . isIdentifier ( current . right ) ) {
238+ parts . unshift ( current . right . name ) ;
239+ }
240+ current = current . left ;
241+ }
242+
243+ if ( t . isIdentifier ( current ) ) {
244+ parts . unshift ( current . name ) ;
245+ }
246+
247+ return parts . join ( '.' ) ;
248+ }
249+ return null ;
250+ }
251+
252+ function findTypeDeclaration ( typeName : string ) {
253+ if ( ! ctx ) return null ;
254+
255+ for ( const statement of ctx . ast ) {
256+ if (
257+ t . isTSInterfaceDeclaration ( statement ) &&
258+ statement . id . name === typeName
259+ ) {
260+ return t . tsTypeLiteral ( statement . body . body ) ;
261+ }
262+
263+ if (
264+ t . isTSTypeAliasDeclaration ( statement ) &&
265+ statement . id . name === typeName
266+ ) {
267+ return statement . typeAnnotation ;
268+ }
269+
270+ if ( t . isExportNamedDeclaration ( statement ) && statement . declaration ) {
271+ if (
272+ t . isTSInterfaceDeclaration ( statement . declaration ) &&
273+ statement . declaration . id . name === typeName
274+ ) {
275+ return t . tsTypeLiteral ( statement . declaration . body . body ) ;
276+ }
277+
278+ if (
279+ t . isTSTypeAliasDeclaration ( statement . declaration ) &&
280+ statement . declaration . id . name === typeName
281+ ) {
282+ return statement . declaration . typeAnnotation ;
283+ }
284+ }
285+ }
286+
287+ return null ;
288+ }
289+ } ) ;
190290export default plugin ;
191291
192292function getTypeAnnotation ( node : BabelCore . types . Node ) {
0 commit comments