@@ -264,7 +264,8 @@ namespace ts.Completions {
264
264
// }
265
265
// let a: A;
266
266
// a['/*completion position*/']
267
- return getStringLiteralCompletionEntriesFromElementAccess ( node . parent , typeChecker , compilerOptions . target , log ) ;
267
+ const type = typeChecker . getTypeAtLocation ( node . parent . expression ) ;
268
+ return getStringLiteralCompletionEntriesFromElementAccessOrIndexedAccess ( node , type , typeChecker , compilerOptions . target , log ) ;
268
269
}
269
270
else if ( node . parent . kind === SyntaxKind . ImportDeclaration || node . parent . kind === SyntaxKind . ExportDeclaration
270
271
|| isRequireCall ( node . parent , /*checkArgumentIsStringLiteral*/ false ) || isImportCall ( node . parent )
@@ -278,6 +279,16 @@ namespace ts.Completions {
278
279
const entries = PathCompletions . getStringLiteralCompletionsFromModuleNames ( node , compilerOptions , host , typeChecker ) ;
279
280
return pathCompletionsInfo ( entries ) ;
280
281
}
282
+ else if ( isIndexedAccessTypeNode ( node . parent . parent ) ) {
283
+ // Get all apparent property names
284
+ // i.e. interface Foo {
285
+ // foo: string;
286
+ // bar: string;
287
+ // }
288
+ // let x: Foo["/*completion position*/"]
289
+ const type = typeChecker . getTypeFromTypeNode ( node . parent . parent . objectType ) ;
290
+ return getStringLiteralCompletionEntriesFromElementAccessOrIndexedAccess ( node , type , typeChecker , compilerOptions . target , log ) ;
291
+ }
281
292
else {
282
293
const argumentInfo = SignatureHelp . getImmediatelyContainingArgumentInfo ( node , position , sourceFile ) ;
283
294
if ( argumentInfo ) {
@@ -334,11 +345,10 @@ namespace ts.Completions {
334
345
return undefined ;
335
346
}
336
347
337
- function getStringLiteralCompletionEntriesFromElementAccess ( node : ElementAccessExpression , typeChecker : TypeChecker , target : ScriptTarget , log : Log ) : CompletionInfo | undefined {
338
- const type = typeChecker . getTypeAtLocation ( node . expression ) ;
348
+ function getStringLiteralCompletionEntriesFromElementAccessOrIndexedAccess ( stringLiteralNode : StringLiteral | NoSubstitutionTemplateLiteral , type : Type , typeChecker : TypeChecker , target : ScriptTarget , log : Log ) : CompletionInfo | undefined {
339
349
const entries : CompletionEntry [ ] = [ ] ;
340
350
if ( type ) {
341
- getCompletionEntriesFromSymbols ( type . getApparentProperties ( ) , entries , node , /*performCharacterChecks*/ false , typeChecker , target , log , /*allowStringLiteral*/ true ) ;
351
+ getCompletionEntriesFromSymbols ( type . getApparentProperties ( ) , entries , stringLiteralNode , /*performCharacterChecks*/ false , typeChecker , target , log , /*allowStringLiteral*/ true ) ;
342
352
if ( entries . length ) {
343
353
return { isGlobalCompletion : false , isMemberCompletion : true , isNewIdentifierLocation : true , entries } ;
344
354
}
@@ -1583,7 +1593,7 @@ namespace ts.Completions {
1583
1593
switch ( contextToken . kind ) {
1584
1594
case SyntaxKind . OpenParenToken :
1585
1595
case SyntaxKind . CommaToken :
1586
- return isConstructorDeclaration ( contextToken . parent ) && contextToken . parent ;
1596
+ return isConstructorDeclaration ( contextToken . parent ) && contextToken . parent ;
1587
1597
1588
1598
default :
1589
1599
if ( isConstructorParameterCompletion ( contextToken ) ) {
0 commit comments