@@ -118,38 +118,46 @@ interface ResolvedElements {
118
118
export function resolveTypeElements (
119
119
ctx : TypeResolveContext ,
120
120
node : Node & MaybeWithScope & { _resolvedElements ?: ResolvedElements } ,
121
- scope ?: TypeScope
121
+ scope ?: TypeScope ,
122
+ typeParameters ?: Record < string , Node >
122
123
) : ResolvedElements {
123
124
if ( node . _resolvedElements ) {
124
125
return node . _resolvedElements
125
126
}
126
127
return ( node . _resolvedElements = innerResolveTypeElements (
127
128
ctx ,
128
129
node ,
129
- node . _ownerScope || scope || ctxToScope ( ctx )
130
+ node . _ownerScope || scope || ctxToScope ( ctx ) ,
131
+ typeParameters
130
132
) )
131
133
}
132
134
133
135
function innerResolveTypeElements (
134
136
ctx : TypeResolveContext ,
135
137
node : Node ,
136
- scope : TypeScope
138
+ scope : TypeScope ,
139
+ typeParameters ?: Record < string , Node >
137
140
) : ResolvedElements {
138
141
switch ( node . type ) {
139
142
case 'TSTypeLiteral' :
140
- return typeElementsToMap ( ctx , node . members , scope )
143
+ return typeElementsToMap ( ctx , node . members , scope , typeParameters )
141
144
case 'TSInterfaceDeclaration' :
142
- return resolveInterfaceMembers ( ctx , node , scope )
145
+ return resolveInterfaceMembers ( ctx , node , scope , typeParameters )
143
146
case 'TSTypeAliasDeclaration' :
144
147
case 'TSParenthesizedType' :
145
- return resolveTypeElements ( ctx , node . typeAnnotation , scope )
148
+ return resolveTypeElements (
149
+ ctx ,
150
+ node . typeAnnotation ,
151
+ scope ,
152
+ typeParameters
153
+ )
146
154
case 'TSFunctionType' : {
147
155
return { props : { } , calls : [ node ] }
148
156
}
149
157
case 'TSUnionType' :
150
158
case 'TSIntersectionType' :
151
159
return mergeElements (
152
- node . types . map ( t => resolveTypeElements ( ctx , t , scope ) ) ,
160
+ node . types . map ( t => resolveTypeElements ( ctx , t , scope , typeParameters ) ) ,
153
161
node . type
154
162
)
155
163
case 'TSMappedType' :
@@ -171,20 +179,57 @@ function innerResolveTypeElements(
171
179
scope . imports [ typeName ] ?. source === 'vue'
172
180
) {
173
181
return resolveExtractPropTypes (
174
- resolveTypeElements ( ctx , node . typeParameters . params [ 0 ] , scope ) ,
182
+ resolveTypeElements (
183
+ ctx ,
184
+ node . typeParameters . params [ 0 ] ,
185
+ scope ,
186
+ typeParameters
187
+ ) ,
175
188
scope
176
189
)
177
190
}
178
191
const resolved = resolveTypeReference ( ctx , node , scope )
179
192
if ( resolved ) {
180
- return resolveTypeElements ( ctx , resolved , resolved . _ownerScope )
193
+ const typeParams : Record < string , Node > = Object . create ( null )
194
+ if (
195
+ ( resolved . type === 'TSTypeAliasDeclaration' ||
196
+ resolved . type === 'TSInterfaceDeclaration' ) &&
197
+ resolved . typeParameters &&
198
+ node . typeParameters
199
+ ) {
200
+ resolved . typeParameters . params . forEach ( ( p , i ) => {
201
+ let param = typeParameters && typeParameters [ p . name ]
202
+ if ( ! param ) param = node . typeParameters ! . params [ i ]
203
+ typeParams [ p . name ] = param
204
+ } )
205
+ }
206
+ return resolveTypeElements (
207
+ ctx ,
208
+ resolved ,
209
+ resolved . _ownerScope ,
210
+ typeParams
211
+ )
181
212
} else {
182
213
if ( typeof typeName === 'string' ) {
214
+ if ( typeParameters && typeParameters [ typeName ] ) {
215
+ return resolveTypeElements (
216
+ ctx ,
217
+ typeParameters [ typeName ] ,
218
+ scope ,
219
+ typeParameters
220
+ )
221
+ }
183
222
if (
184
223
// @ts -ignore
185
224
SupportedBuiltinsSet . has ( typeName )
186
225
) {
187
- return resolveBuiltin ( ctx , node , typeName as any , scope )
226
+ return resolveBuiltin (
227
+ ctx ,
228
+ node ,
229
+ typeName as any ,
230
+ scope ,
231
+ typeParameters
232
+ )
188
233
} else if ( typeName === 'ReturnType' && node . typeParameters ) {
189
234
// limited support, only reference types
190
235
const ret = resolveReturnType (
@@ -243,11 +288,17 @@ function innerResolveTypeElements(
243
288
function typeElementsToMap (
244
289
ctx : TypeResolveContext ,
245
290
elements : TSTypeElement [ ] ,
246
- scope = ctxToScope ( ctx )
291
+ scope = ctxToScope ( ctx ) ,
292
+ typeParameters ?: Record < string , Node >
247
293
) : ResolvedElements {
248
294
const res : ResolvedElements = { props : { } }
249
295
for ( const e of elements ) {
250
296
if ( e . type === 'TSPropertySignature' || e . type === 'TSMethodSignature' ) {
297
+ // capture generic parameters on node's scope
298
+ if ( typeParameters ) {
299
+ scope = createChildScope ( scope )
300
+ Object . assign ( scope . types , typeParameters )
301
+ }
251
302
; ( e as MaybeWithScope ) . _ownerScope = scope
252
303
const name = getId ( e . key )
253
304
if ( name && ! e . computed ) {
@@ -323,9 +374,15 @@ function createProperty(
323
374
function resolveInterfaceMembers (
324
375
ctx : TypeResolveContext ,
325
376
node : TSInterfaceDeclaration & MaybeWithScope ,
326
- scope : TypeScope
377
+ scope : TypeScope ,
378
+ typeParameters ?: Record < string , Node >
327
379
) : ResolvedElements {
328
- const base = typeElementsToMap ( ctx , node . body . body , node . _ownerScope )
380
+ const base = typeElementsToMap (
381
+ ctx ,
382
+ node . body . body ,
383
+ node . _ownerScope ,
384
+ typeParameters
385
+ )
329
386
if ( node . extends ) {
330
387
for ( const ext of node . extends ) {
331
388
if (
@@ -543,9 +600,15 @@ function resolveBuiltin(
543
600
ctx : TypeResolveContext ,
544
601
node : TSTypeReference | TSExpressionWithTypeArguments ,
545
602
name : GetSetType < typeof SupportedBuiltinsSet > ,
546
- scope : TypeScope
603
+ scope : TypeScope ,
604
+ typeParameters ?: Record < string , Node >
547
605
) : ResolvedElements {
548
- const t = resolveTypeElements ( ctx , node . typeParameters ! . params [ 0 ] , scope )
606
+ const t = resolveTypeElements (
607
+ ctx ,
608
+ node . typeParameters ! . params [ 0 ] ,
609
+ scope ,
610
+ typeParameters
611
+ )
549
612
switch ( name ) {
550
613
case 'Partial' : {
551
614
const res : ResolvedElements = { props : { } , calls : t . calls }
@@ -1103,14 +1166,7 @@ function moduleDeclToScope(
1103
1166
return node . _resolvedChildScope
1104
1167
}
1105
1168
1106
- const scope = new TypeScope (
1107
- parentScope . filename ,
1108
- parentScope . source ,
1109
- parentScope . offset ,
1110
- Object . create ( parentScope . imports ) ,
1111
- Object . create ( parentScope . types ) ,
1112
- Object . create ( parentScope . declares )
1113
- )
1169
+ const scope = createChildScope ( parentScope )
1114
1170
1115
1171
if ( node . body . type === 'TSModuleDeclaration' ) {
1116
1172
const decl = node . body as TSModuleDeclaration & WithScope
@@ -1124,6 +1180,17 @@ function moduleDeclToScope(
1124
1180
return ( node . _resolvedChildScope = scope )
1125
1181
}
1126
1182
1183
+ function createChildScope ( parentScope : TypeScope ) {
1184
+ return new TypeScope (
1185
+ parentScope . filename ,
1186
+ parentScope . source ,
1187
+ parentScope . offset ,
1188
+ Object . create ( parentScope . imports ) ,
1189
+ Object . create ( parentScope . types ) ,
1190
+ Object . create ( parentScope . declares )
1191
+ )
1192
+ }
1193
+
1127
1194
const importExportRE = / ^ I m p o r t | ^ E x p o r t /
1128
1195
1129
1196
function recordTypes (
@@ -1262,7 +1329,7 @@ function recordType(
1262
1329
if ( overwriteId || node . id ) types [ overwriteId || getId ( node . id ! ) ] = node
1263
1330
break
1264
1331
case 'TSTypeAliasDeclaration' :
1265
- types [ node . id . name ] = node . typeAnnotation
1332
+ types [ node . id . name ] = node . typeParameters ? node : node . typeAnnotation
1266
1333
break
1267
1334
case 'TSDeclareFunction' :
1268
1335
if ( node . id ) declares [ node . id . name ] = node
0 commit comments