diff --git a/src/services/stringCompletions.ts b/src/services/stringCompletions.ts index 150d0652dd28c..14b83b84a2602 100644 --- a/src/services/stringCompletions.ts +++ b/src/services/stringCompletions.ts @@ -495,7 +495,7 @@ function getStringLiteralCompletionsFromSignature(call: CallLikeExpression, arg: } } isNewIdentifier = isNewIdentifier || !!(type.flags & TypeFlags.String); - return getStringLiteralTypes(type, uniques); + return getStringLiteralTypes(type, uniques, arg.text); }); return length(types) ? { kind: StringLiteralCompletionKind.Types, types, isNewIdentifier } : undefined; } @@ -527,11 +527,11 @@ function stringLiteralCompletionsForObjectLiteral(checker: TypeChecker, objectLi }; } -function getStringLiteralTypes(type: Type | undefined, uniques = new Map()): readonly StringLiteralType[] { +function getStringLiteralTypes(type: Type | undefined, uniques = new Map(), alreadyTyped = ""): readonly StringLiteralType[] { if (!type) return emptyArray; type = skipConstraint(type); - return type.isUnion() ? flatMap(type.types, t => getStringLiteralTypes(t, uniques)) : - type.isStringLiteral() && !(type.flags & TypeFlags.EnumLiteral) && addToSeen(uniques, type.value) ? [type] : emptyArray; + return type.isUnion() ? flatMap(type.types, t => getStringLiteralTypes(t, uniques, alreadyTyped)) : + type.isStringLiteral() && !(type.flags & TypeFlags.EnumLiteral) && type.value.startsWith(alreadyTyped) && addToSeen(uniques, type.value) ? [type] : emptyArray; } interface NameAndKind { diff --git a/tests/cases/fourslash/stringCompletionsFromGenericConditionalTypesUsingTemplateLiteralTypes.ts b/tests/cases/fourslash/stringCompletionsFromGenericConditionalTypesUsingTemplateLiteralTypes.ts new file mode 100644 index 0000000000000..97665f57dc8ee --- /dev/null +++ b/tests/cases/fourslash/stringCompletionsFromGenericConditionalTypesUsingTemplateLiteralTypes.ts @@ -0,0 +1,13 @@ +/// + +// @Filename: /a.tsx +//// type PathOf = +//// K extends `${infer U}.${infer V}` +//// ? U extends keyof T ? PathOf : `${P}${keyof T & (string | number)}` +//// : K extends keyof T ? `${P}${K}` : `${P}${keyof T & (string | number)}`; +//// +//// declare function consumer(path: PathOf<{a: string, b: {c: string}}, K>) : number; +//// +//// consumer('b./*ts*/') + +verify.completions({ marker: ["ts"], exact: ["b.c"] });