@@ -264,7 +264,8 @@ namespace ts.Completions {
264264 // }
265265 // let a: A;
266266 // 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 ) ;
268269 }
269270 else if ( node . parent . kind === SyntaxKind . ImportDeclaration || node . parent . kind === SyntaxKind . ExportDeclaration
270271 || isRequireCall ( node . parent , /*checkArgumentIsStringLiteral*/ false ) || isImportCall ( node . parent )
@@ -278,6 +279,16 @@ namespace ts.Completions {
278279 const entries = PathCompletions . getStringLiteralCompletionsFromModuleNames ( node , compilerOptions , host , typeChecker ) ;
279280 return pathCompletionsInfo ( entries ) ;
280281 }
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+ }
281292 else {
282293 const argumentInfo = SignatureHelp . getImmediatelyContainingArgumentInfo ( node , position , sourceFile ) ;
283294 if ( argumentInfo ) {
@@ -334,11 +345,10 @@ namespace ts.Completions {
334345 return undefined ;
335346 }
336347
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 {
339349 const entries : CompletionEntry [ ] = [ ] ;
340350 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 ) ;
342352 if ( entries . length ) {
343353 return { isGlobalCompletion : false , isMemberCompletion : true , isNewIdentifierLocation : true , entries } ;
344354 }
@@ -1583,7 +1593,7 @@ namespace ts.Completions {
15831593 switch ( contextToken . kind ) {
15841594 case SyntaxKind . OpenParenToken :
15851595 case SyntaxKind . CommaToken :
1586- return isConstructorDeclaration ( contextToken . parent ) && contextToken . parent ;
1596+ return isConstructorDeclaration ( contextToken . parent ) && contextToken . parent ;
15871597
15881598 default :
15891599 if ( isConstructorParameterCompletion ( contextToken ) ) {
0 commit comments