diff --git a/src/services/completions.ts b/src/services/completions.ts index 810a7dfdebe..01584d6a5e1 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -2676,7 +2676,7 @@ namespace ts.Completions { return jsdoc && jsdoc.tags && (rangeContainsPosition(jsdoc, position) ? findLast(jsdoc.tags, tag => tag.pos < position) : undefined); } - function getPropertiesForObjectExpression(contextualType: Type, completionsType: Type | undefined, obj: ObjectLiteralExpression | JsxAttributes, checker: TypeChecker): Symbol[] { + export function getPropertiesForObjectExpression(contextualType: Type, completionsType: Type | undefined, obj: ObjectLiteralExpression | JsxAttributes, checker: TypeChecker): Symbol[] { const hasCompletionsType = completionsType && completionsType !== contextualType; const type = hasCompletionsType && !(completionsType!.flags & TypeFlags.AnyOrUnknown) ? checker.getUnionType([contextualType, completionsType!]) diff --git a/src/services/stringCompletions.ts b/src/services/stringCompletions.ts index a355a791695..de823ad951d 100644 --- a/src/services/stringCompletions.ts +++ b/src/services/stringCompletions.ts @@ -163,7 +163,7 @@ namespace ts.Completions.StringCompletions { // foo({ // '/*completion position*/' // }); - return stringLiteralCompletionsFromProperties(typeChecker.getContextualType(parent.parent)); + return stringLiteralCompletionsForObjectLiteral(typeChecker, parent.parent); } return fromContextualType(); @@ -254,6 +254,25 @@ namespace ts.Completions.StringCompletions { }; } + function stringLiteralCompletionsForObjectLiteral(checker: TypeChecker, objectLiteralExpression: ObjectLiteralExpression): StringLiteralCompletionsFromProperties | undefined { + const contextualType = checker.getContextualType(objectLiteralExpression); + if (!contextualType) return undefined; + + const completionsType = checker.getContextualType(objectLiteralExpression, ContextFlags.Completions); + const symbols = getPropertiesForObjectExpression( + contextualType, + completionsType, + objectLiteralExpression, + checker + ); + + return { + kind: StringLiteralCompletionKind.Properties, + symbols, + hasIndexSignature: hasIndexSignature(contextualType) + }; + } + function getStringLiteralTypes(type: Type | undefined, uniques = new Map()): readonly StringLiteralType[] { if (!type) return emptyArray; type = skipConstraint(type); diff --git a/tests/cases/fourslash/completionsQuotedObjectLiteralUnion.ts b/tests/cases/fourslash/completionsQuotedObjectLiteralUnion.ts new file mode 100644 index 00000000000..9cfdafa68cc --- /dev/null +++ b/tests/cases/fourslash/completionsQuotedObjectLiteralUnion.ts @@ -0,0 +1,18 @@ +/// + +//// interface A { +//// "a-prop": string; +//// } +//// +//// interface B { +//// "b-prop": string; +//// } +//// +//// const obj: A | B = { +//// "/*1*/" +//// } + +verify.completions({ + marker: "1", + exact: ["a-prop", "b-prop"] +});