@@ -1500,6 +1500,7 @@ export function inferRuntimeType(
1500
1500
node : Node & MaybeWithScope ,
1501
1501
scope : TypeScope = node . _ownerScope || ctxToScope ( ctx ) ,
1502
1502
isKeyOf = false ,
1503
+ typeParameters ?: Record < string , Node > ,
1503
1504
) : string [ ] {
1504
1505
try {
1505
1506
switch ( node . type ) {
@@ -1588,19 +1589,43 @@ export function inferRuntimeType(
1588
1589
case 'TSTypeReference' : {
1589
1590
const resolved = resolveTypeReference ( ctx , node , scope )
1590
1591
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
+ }
1599
1615
}
1616
+
1600
1617
return inferRuntimeType ( ctx , resolved , resolved . _ownerScope , isKeyOf )
1601
1618
}
1602
-
1603
1619
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
+ }
1604
1629
if ( isKeyOf ) {
1605
1630
switch ( node . typeName . name ) {
1606
1631
case 'String' :
@@ -1733,11 +1758,15 @@ export function inferRuntimeType(
1733
1758
return inferRuntimeType ( ctx , node . typeAnnotation , scope )
1734
1759
1735
1760
case 'TSUnionType' :
1736
- return flattenTypes ( ctx , node . types , scope , isKeyOf )
1761
+ return flattenTypes ( ctx , node . types , scope , isKeyOf , typeParameters )
1737
1762
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 )
1741
1770
}
1742
1771
1743
1772
case 'TSEnumDeclaration' :
@@ -1808,14 +1837,17 @@ function flattenTypes(
1808
1837
types : TSType [ ] ,
1809
1838
scope : TypeScope ,
1810
1839
isKeyOf : boolean = false ,
1840
+ typeParameters : Record < string , Node > | undefined = undefined ,
1811
1841
) : string [ ] {
1812
1842
if ( types . length === 1 ) {
1813
- return inferRuntimeType ( ctx , types [ 0 ] , scope , isKeyOf )
1843
+ return inferRuntimeType ( ctx , types [ 0 ] , scope , isKeyOf , typeParameters )
1814
1844
}
1815
1845
return [
1816
1846
...new Set (
1817
1847
( [ ] as string [ ] ) . concat (
1818
- ...types . map ( t => inferRuntimeType ( ctx , t , scope , isKeyOf ) ) ,
1848
+ ...types . map ( t =>
1849
+ inferRuntimeType ( ctx , t , scope , isKeyOf , typeParameters ) ,
1850
+ ) ,
1819
1851
) ,
1820
1852
) ,
1821
1853
]
0 commit comments