@@ -1448,7 +1448,10 @@ export function inferRuntimeType(
1448
1448
ctx : TypeResolveContext ,
1449
1449
node : Node & MaybeWithScope ,
1450
1450
scope = node . _ownerScope || ctxToScope ( ctx ) ,
1451
+ options : { isKeyof ?: boolean } = { } ,
1451
1452
) : string [ ] {
1453
+ const { isKeyof } = options
1454
+
1452
1455
try {
1453
1456
switch ( node . type ) {
1454
1457
case 'TSStringKeyword' :
@@ -1467,16 +1470,33 @@ export function inferRuntimeType(
1467
1470
const types = new Set < string > ( )
1468
1471
const members =
1469
1472
node . type === 'TSTypeLiteral' ? node . members : node . body . body
1473
+
1474
+ const handler = isKeyof
1475
+ ? ( m : TSTypeElement ) => {
1476
+ if (
1477
+ m . type === 'TSPropertySignature' &&
1478
+ m . key . type === 'NumericLiteral'
1479
+ ) {
1480
+ types . add ( 'Number' )
1481
+ } else {
1482
+ types . add ( 'String' )
1483
+ }
1484
+ }
1485
+ : ( m : TSTypeElement ) => {
1486
+ if (
1487
+ m . type === 'TSCallSignatureDeclaration' ||
1488
+ m . type === 'TSConstructSignatureDeclaration'
1489
+ ) {
1490
+ types . add ( 'Function' )
1491
+ } else {
1492
+ types . add ( 'Object' )
1493
+ }
1494
+ }
1495
+
1470
1496
for ( const m of members ) {
1471
- if (
1472
- m . type === 'TSCallSignatureDeclaration' ||
1473
- m . type === 'TSConstructSignatureDeclaration'
1474
- ) {
1475
- types . add ( 'Function' )
1476
- } else {
1477
- types . add ( 'Object' )
1478
- }
1497
+ handler ( m )
1479
1498
}
1499
+
1480
1500
return types . size ? Array . from ( types ) : [ 'Object' ]
1481
1501
}
1482
1502
case 'TSPropertySignature' :
@@ -1512,8 +1532,11 @@ export function inferRuntimeType(
1512
1532
case 'TSTypeReference' : {
1513
1533
const resolved = resolveTypeReference ( ctx , node , scope )
1514
1534
if ( resolved ) {
1515
- return inferRuntimeType ( ctx , resolved , resolved . _ownerScope )
1535
+ return inferRuntimeType ( ctx , resolved , resolved . _ownerScope , options )
1516
1536
}
1537
+
1538
+ if ( isKeyof ) return [ 'String' ]
1539
+
1517
1540
if ( node . typeName . type === 'Identifier' ) {
1518
1541
switch ( node . typeName . name ) {
1519
1542
case 'Array' :
@@ -1634,15 +1657,17 @@ export function inferRuntimeType(
1634
1657
// typeof only support identifier in local scope
1635
1658
const matched = scope . declares [ id . name ]
1636
1659
if ( matched ) {
1637
- return inferRuntimeType ( ctx , matched , matched . _ownerScope )
1660
+ return inferRuntimeType ( ctx , matched , matched . _ownerScope , options )
1638
1661
}
1639
1662
}
1640
1663
break
1641
1664
}
1642
1665
1643
1666
// e.g. readonly
1644
1667
case 'TSTypeOperator' : {
1645
- return inferRuntimeType ( ctx , node . typeAnnotation , scope )
1668
+ return inferRuntimeType ( ctx , node . typeAnnotation , scope , {
1669
+ isKeyof : node . operator === 'keyof' ,
1670
+ } )
1646
1671
}
1647
1672
}
1648
1673
} catch ( e ) {
0 commit comments