@@ -1448,6 +1448,7 @@ export function inferRuntimeType(
14481448 ctx : TypeResolveContext ,
14491449 node : Node & MaybeWithScope ,
14501450 scope = node . _ownerScope || ctxToScope ( ctx ) ,
1451+ isKeyOf = false ,
14511452) : string [ ] {
14521453 try {
14531454 switch ( node . type ) {
@@ -1467,8 +1468,18 @@ export function inferRuntimeType(
14671468 const types = new Set < string > ( )
14681469 const members =
14691470 node . type === 'TSTypeLiteral' ? node . members : node . body . body
1471+
14701472 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 (
14721483 m . type === 'TSCallSignatureDeclaration' ||
14731484 m . type === 'TSConstructSignatureDeclaration'
14741485 ) {
@@ -1477,6 +1488,7 @@ export function inferRuntimeType(
14771488 types . add ( 'Object' )
14781489 }
14791490 }
1491+
14801492 return types . size ? Array . from ( types ) : [ 'Object' ]
14811493 }
14821494 case 'TSPropertySignature' :
@@ -1512,9 +1524,22 @@ export function inferRuntimeType(
15121524 case 'TSTypeReference' : {
15131525 const resolved = resolveTypeReference ( ctx , node , scope )
15141526 if ( resolved ) {
1515- return inferRuntimeType ( ctx , resolved , resolved . _ownerScope )
1527+ return inferRuntimeType ( ctx , resolved , resolved . _ownerScope , isKeyOf )
15161528 }
1529+
15171530 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+
15181543 switch ( node . typeName . name ) {
15191544 case 'Array' :
15201545 case 'Function' :
@@ -1634,15 +1659,20 @@ export function inferRuntimeType(
16341659 // typeof only support identifier in local scope
16351660 const matched = scope . declares [ id . name ]
16361661 if ( matched ) {
1637- return inferRuntimeType ( ctx , matched , matched . _ownerScope )
1662+ return inferRuntimeType ( ctx , matched , matched . _ownerScope , isKeyOf )
16381663 }
16391664 }
16401665 break
16411666 }
16421667
16431668 // e.g. readonly
16441669 case 'TSTypeOperator' : {
1645- return inferRuntimeType ( ctx , node . typeAnnotation , scope )
1670+ return inferRuntimeType (
1671+ ctx ,
1672+ node . typeAnnotation ,
1673+ scope ,
1674+ node . operator === 'keyof' ,
1675+ )
16461676 }
16471677 }
16481678 } catch ( e ) {
0 commit comments