@@ -1448,6 +1448,7 @@ export function inferRuntimeType(
1448
1448
ctx : TypeResolveContext ,
1449
1449
node : Node & MaybeWithScope ,
1450
1450
scope = node . _ownerScope || ctxToScope ( ctx ) ,
1451
+ isKeyOf = false ,
1451
1452
) : string [ ] {
1452
1453
try {
1453
1454
switch ( node . type ) {
@@ -1467,8 +1468,18 @@ export function inferRuntimeType(
1467
1468
const types = new Set < string > ( )
1468
1469
const members =
1469
1470
node . type === 'TSTypeLiteral' ? node . members : node . body . body
1471
+
1470
1472
for ( const m of members ) {
1471
- if (
1473
+ if ( isKeyOf ) {
1474
+ if (
1475
+ m . type === 'TSPropertySignature' &&
1476
+ m . key . type === 'NumericLiteral'
1477
+ ) {
1478
+ types . add ( 'Number' )
1479
+ } else {
1480
+ types . add ( 'String' )
1481
+ }
1482
+ } else if (
1472
1483
m . type === 'TSCallSignatureDeclaration' ||
1473
1484
m . type === 'TSConstructSignatureDeclaration'
1474
1485
) {
@@ -1477,6 +1488,7 @@ export function inferRuntimeType(
1477
1488
types . add ( 'Object' )
1478
1489
}
1479
1490
}
1491
+
1480
1492
return types . size ? Array . from ( types ) : [ 'Object' ]
1481
1493
}
1482
1494
case 'TSPropertySignature' :
@@ -1512,9 +1524,22 @@ export function inferRuntimeType(
1512
1524
case 'TSTypeReference' : {
1513
1525
const resolved = resolveTypeReference ( ctx , node , scope )
1514
1526
if ( resolved ) {
1515
- return inferRuntimeType ( ctx , resolved , resolved . _ownerScope )
1527
+ return inferRuntimeType ( ctx , resolved , resolved . _ownerScope , isKeyOf )
1516
1528
}
1529
+
1517
1530
if ( node . typeName . type === 'Identifier' ) {
1531
+ if ( isKeyOf ) {
1532
+ switch ( node . typeName . name ) {
1533
+ case 'String' :
1534
+ case 'Array' :
1535
+ case 'ArrayLike' :
1536
+ case 'ReadonlyArray' :
1537
+ return [ 'String' , 'Number' ]
1538
+ default :
1539
+ return [ 'String' ]
1540
+ }
1541
+ }
1542
+
1518
1543
switch ( node . typeName . name ) {
1519
1544
case 'Array' :
1520
1545
case 'Function' :
@@ -1634,15 +1659,20 @@ export function inferRuntimeType(
1634
1659
// typeof only support identifier in local scope
1635
1660
const matched = scope . declares [ id . name ]
1636
1661
if ( matched ) {
1637
- return inferRuntimeType ( ctx , matched , matched . _ownerScope )
1662
+ return inferRuntimeType ( ctx , matched , matched . _ownerScope , isKeyOf )
1638
1663
}
1639
1664
}
1640
1665
break
1641
1666
}
1642
1667
1643
1668
// e.g. readonly
1644
1669
case 'TSTypeOperator' : {
1645
- return inferRuntimeType ( ctx , node . typeAnnotation , scope )
1670
+ return inferRuntimeType (
1671
+ ctx ,
1672
+ node . typeAnnotation ,
1673
+ scope ,
1674
+ node . operator === 'keyof' ,
1675
+ )
1646
1676
}
1647
1677
}
1648
1678
} catch ( e ) {
0 commit comments