diff --git a/src/services/services.ts b/src/services/services.ts index 1c079b84027..72255b55479 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -3504,7 +3504,18 @@ namespace ts { // We don't want to complete using the type acquired by the shape // of the binding pattern; we are only interested in types acquired // through type declaration or inference. - if (rootDeclaration.initializer || rootDeclaration.type) { + // Also proceed if rootDeclaration is parameter and if its containing function expression\arrow function is contextually typed - + // type of parameter will flow in from the contextual type of the function + let canGetType = !!(rootDeclaration.initializer || rootDeclaration.type); + if (!canGetType && rootDeclaration.kind === SyntaxKind.Parameter) { + if (isExpression(rootDeclaration.parent)) { + canGetType = !!typeChecker.getContextualType(rootDeclaration.parent); + } + else if (rootDeclaration.parent.kind === SyntaxKind.MethodDeclaration || rootDeclaration.parent.kind === SyntaxKind.SetAccessor) { + canGetType = isExpression(rootDeclaration.parent.parent) && !!typeChecker.getContextualType(rootDeclaration.parent.parent); + } + } + if (canGetType) { typeForObject = typeChecker.getTypeAtLocation(objectLikeContainer); existingMembers = (objectLikeContainer).elements; } diff --git a/tests/cases/fourslash/objectLiteralBindingInParameter.ts b/tests/cases/fourslash/objectLiteralBindingInParameter.ts new file mode 100644 index 00000000000..b1cbd21d929 --- /dev/null +++ b/tests/cases/fourslash/objectLiteralBindingInParameter.ts @@ -0,0 +1,35 @@ +/// + +////interface I { x1: number; x2: string } +////function f(cb: (ev: I) => any) { } +////f(({/*1*/}) => 0); + +////[null].reduce(({/*2*/}, b) => b); + +////interface Foo { +//// m(x: { x1: number, x2: number }): void; +//// prop: I; +////} +////let x: Foo = { +//// m({ /*3*/ }) { +//// }, +//// get prop(): I { return undefined; }, +//// set prop({ /*4*/ }) { +//// } +////}; + +goTo.marker("1"); +verify.completionListContains("x1"); +verify.completionListContains("x2"); + +goTo.marker("2"); +verify.completionListContains("x1"); +verify.completionListContains("x2"); + +goTo.marker("3"); +verify.completionListContains("x1"); +verify.completionListContains("x2"); + +goTo.marker("4"); +verify.completionListContains("x1"); +verify.completionListContains("x2"); \ No newline at end of file