@@ -1500,6 +1500,7 @@ export function inferRuntimeType(
15001500 node : Node & MaybeWithScope ,
15011501 scope : TypeScope = node . _ownerScope || ctxToScope ( ctx ) ,
15021502 isKeyOf = false ,
1503+ typeParameters ?: Record < string , Node > ,
15031504) : string [ ] {
15041505 try {
15051506 switch ( node . type ) {
@@ -1588,19 +1589,43 @@ export function inferRuntimeType(
15881589 case 'TSTypeReference' : {
15891590 const resolved = resolveTypeReference ( ctx , node , scope )
15901591 if ( resolved ) {
1591- // #13240
1592- // Special case for function type aliases to ensure correct runtime behavior
1593- // other type aliases still fallback to unknown as before
1594- if (
1595- resolved . type === 'TSTypeAliasDeclaration' &&
1596- resolved . typeAnnotation . type === 'TSFunctionType'
1597- ) {
1598- return [ 'Function' ]
1592+ if ( resolved . type === 'TSTypeAliasDeclaration' ) {
1593+ // #13240
1594+ // Special case for function type aliases to ensure correct runtime behavior
1595+ // other type aliases still fallback to unknown as before
1596+ if ( resolved . typeAnnotation . type === 'TSFunctionType' ) {
1597+ return [ 'Function' ]
1598+ }
1599+
1600+ if ( node . typeParameters ) {
1601+ const typeParams : Record < string , Node > = Object . create ( null )
1602+ if ( resolved . typeParameters ) {
1603+ resolved . typeParameters . params . forEach ( ( p , i ) => {
1604+ typeParams ! [ p . name ] = node . typeParameters ! . params [ i ]
1605+ } )
1606+ }
1607+ return inferRuntimeType (
1608+ ctx ,
1609+ resolved . typeAnnotation ,
1610+ resolved . _ownerScope ,
1611+ isKeyOf ,
1612+ typeParams ,
1613+ )
1614+ }
15991615 }
1616+
16001617 return inferRuntimeType ( ctx , resolved , resolved . _ownerScope , isKeyOf )
16011618 }
1602-
16031619 if ( node . typeName . type === 'Identifier' ) {
1620+ if ( typeParameters && typeParameters [ node . typeName . name ] ) {
1621+ return inferRuntimeType (
1622+ ctx ,
1623+ typeParameters [ node . typeName . name ] ,
1624+ scope ,
1625+ isKeyOf ,
1626+ typeParameters ,
1627+ )
1628+ }
16041629 if ( isKeyOf ) {
16051630 switch ( node . typeName . name ) {
16061631 case 'String' :
@@ -1733,11 +1758,15 @@ export function inferRuntimeType(
17331758 return inferRuntimeType ( ctx , node . typeAnnotation , scope )
17341759
17351760 case 'TSUnionType' :
1736- return flattenTypes ( ctx , node . types , scope , isKeyOf )
1761+ return flattenTypes ( ctx , node . types , scope , isKeyOf , typeParameters )
17371762 case 'TSIntersectionType' : {
1738- return flattenTypes ( ctx , node . types , scope , isKeyOf ) . filter (
1739- t => t !== UNKNOWN_TYPE ,
1740- )
1763+ return flattenTypes (
1764+ ctx ,
1765+ node . types ,
1766+ scope ,
1767+ isKeyOf ,
1768+ typeParameters ,
1769+ ) . filter ( t => t !== UNKNOWN_TYPE )
17411770 }
17421771
17431772 case 'TSEnumDeclaration' :
@@ -1808,14 +1837,17 @@ function flattenTypes(
18081837 types : TSType [ ] ,
18091838 scope : TypeScope ,
18101839 isKeyOf : boolean = false ,
1840+ typeParameters : Record < string , Node > | undefined = undefined ,
18111841) : string [ ] {
18121842 if ( types . length === 1 ) {
1813- return inferRuntimeType ( ctx , types [ 0 ] , scope , isKeyOf )
1843+ return inferRuntimeType ( ctx , types [ 0 ] , scope , isKeyOf , typeParameters )
18141844 }
18151845 return [
18161846 ...new Set (
18171847 ( [ ] as string [ ] ) . concat (
1818- ...types . map ( t => inferRuntimeType ( ctx , t , scope , isKeyOf ) ) ,
1848+ ...types . map ( t =>
1849+ inferRuntimeType ( ctx , t , scope , isKeyOf , typeParameters ) ,
1850+ ) ,
18191851 ) ,
18201852 ) ,
18211853 ]
0 commit comments