@@ -84,8 +84,17 @@ const plugin: (
84
84
node . arguments . push ( options ) ;
85
85
}
86
86
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 ;
89
98
} ,
90
99
VariableDeclarator ( path ) {
91
100
inferComponentName ( path ) ;
@@ -125,6 +134,7 @@ const plugin: (
125
134
126
135
function processProps (
127
136
comp : BabelCore . types . Function ,
137
+ generics : BabelCore . types . TSType | undefined ,
128
138
options :
129
139
| BabelCore . types . ArgumentPlaceholder
130
140
| BabelCore . types . SpreadElement
@@ -134,10 +144,18 @@ const plugin: (
134
144
if ( ! props ) return ;
135
145
136
146
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
+ }
138
152
ctx ! . propsRuntimeDefaults = props . right ;
139
153
} else {
140
- ctx ! . propsTypeDecl = getTypeAnnotation ( props ) ;
154
+ if ( generics ) {
155
+ ctx ! . propsTypeDecl = resolveTypeReference ( generics ) ;
156
+ } else {
157
+ ctx ! . propsTypeDecl = getTypeAnnotation ( props ) ;
158
+ }
141
159
}
142
160
143
161
if ( ! ctx ! . propsTypeDecl ) return ;
@@ -157,20 +175,26 @@ const plugin: (
157
175
158
176
function processEmits (
159
177
comp : BabelCore . types . Function ,
178
+ generics : BabelCore . types . TSType | undefined ,
160
179
options :
161
180
| BabelCore . types . ArgumentPlaceholder
162
181
| BabelCore . types . SpreadElement
163
182
| BabelCore . types . Expression
164
183
) {
184
+ let emitType : BabelCore . types . Node | undefined ;
185
+ if ( generics ) {
186
+ emitType = resolveTypeReference ( generics ) ;
187
+ }
188
+
165
189
const setupCtx = comp . params [ 1 ] && getTypeAnnotation ( comp . params [ 1 ] ) ;
166
190
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
+ }
174
198
if ( ! emitType ) return ;
175
199
176
200
ctx ! . emitsTypeDecl = emitType ;
@@ -185,8 +209,84 @@ const plugin: (
185
209
t . objectProperty ( t . identifier ( 'emits' ) , ast )
186
210
) ;
187
211
}
188
- } ) ;
189
212
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
+ } ) ;
190
290
export default plugin ;
191
291
192
292
function getTypeAnnotation ( node : BabelCore . types . Node ) {
0 commit comments