diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7fcd96913ae06..3c2e75a2eb53b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -30577,6 +30577,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { ); } + function filterContextualTypeForLiteralExpressionOfObject(node: Node, contextualType: Type) { + if (!isLiteralExpressionOfObject(node)) { + return contextualType; + } + return filterType(contextualType, t => { + if (!t.symbol || !(t.symbol.flags & SymbolFlags.Class)) { + return true; + } + return every(getPropertiesOfType(t), p => !p.valueDeclaration || !isNamedDeclaration(p.valueDeclaration) || (!isPrivateIdentifier(p.valueDeclaration.name) && !(getDeclarationModifierFlagsFromSymbol(p) & ModifierFlags.NonPublicAccessibilityModifier))); + }); + } + // Return the contextual type for a given expression node. During overload resolution, a contextual type may temporarily // be "pushed" onto a node using the contextualType property. function getApparentTypeOfContextualType(node: Expression | MethodDeclaration, contextFlags: ContextFlags | undefined): Type | undefined { @@ -30671,6 +30683,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (index >= 0) { return contextualTypes[index]; } + const contextualType = getContextualTypeWorker(node, contextFlags); + if (!contextualType) { + return undefined; + } + return filterContextualTypeForLiteralExpressionOfObject(node, contextualType); + } + + function getContextualTypeWorker(node: Expression, contextFlags: ContextFlags | undefined): Type | undefined { const { parent } = node; switch (parent.kind) { case SyntaxKind.VariableDeclaration: @@ -38810,6 +38830,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function checkExpressionWithContextualType(node: Expression, contextualType: Type, inferenceContext: InferenceContext | undefined, checkMode: CheckMode): Type { + contextualType = filterContextualTypeForLiteralExpressionOfObject(node, contextualType); const contextNode = getContextNode(node); pushContextualType(contextNode, contextualType, /*isCache*/ false); pushInferenceContext(contextNode, inferenceContext); diff --git a/src/services/completions.ts b/src/services/completions.ts index 155d048562b78..40ec73398878d 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -205,6 +205,7 @@ import { isModifier, isModifierKind, isModuleDeclaration, + isNamedDeclaration, isNamedExports, isNamedImports, isNamedImportsOrExports, @@ -5401,7 +5402,7 @@ function getApparentProperties(type: Type, node: ObjectLiteralExpression | JsxAt } function containsNonPublicProperties(props: Symbol[]) { - return some(props, p => !!(getDeclarationModifierFlagsFromSymbol(p) & ModifierFlags.NonPublicAccessibilityModifier)); + return some(props, p => !!(getDeclarationModifierFlagsFromSymbol(p) & ModifierFlags.NonPublicAccessibilityModifier) || !!p.valueDeclaration && isNamedDeclaration(p.valueDeclaration) && isPrivateIdentifier(p.valueDeclaration.name)); } /** diff --git a/tests/baselines/reference/contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.errors.txt b/tests/baselines/reference/contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.errors.txt new file mode 100644 index 0000000000000..21d2b8fab2565 --- /dev/null +++ b/tests/baselines/reference/contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.errors.txt @@ -0,0 +1,41 @@ +contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts(18,8): error TS2345: Argument of type '{ doStuff: (arg: any) => void; }' is not assignable to parameter of type 'Foo'. + Property '#foo' is missing in type '{ doStuff: (arg: any) => void; }' but required in type 'Foo'. +contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts(19,13): error TS7006: Parameter 'arg' implicitly has an 'any' type. + + +==== contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts (2 errors) ==== + class Foo { + #foo = "foo"; + doStuff(cb: (arg: string) => void) {} + } + + interface FooLike { + doStuff: (cb: (arg: number) => void) => void; + } + + declare function useIt(arg: Foo | FooLike): void; + + useIt({ + doStuff: (arg) => {}, + }); + + declare function useIt2(arg: Foo): void; + + useIt2({ + ~ + doStuff: (arg) => {}, + ~~~~~~~~~~~~~~~~~~~~~~~ + ~~~ +!!! error TS7006: Parameter 'arg' implicitly has an 'any' type. + }); + ~ +!!! error TS2345: Argument of type '{ doStuff: (arg: any) => void; }' is not assignable to parameter of type 'Foo'. +!!! error TS2345: Property '#foo' is missing in type '{ doStuff: (arg: any) => void; }' but required in type 'Foo'. +!!! related TS2728 contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts:2:3: '#foo' is declared here. + + declare function useIt3(arg: FooLike): void; + + useIt3({ + doStuff: (arg) => {}, + }); + \ No newline at end of file diff --git a/tests/baselines/reference/contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.symbols b/tests/baselines/reference/contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.symbols new file mode 100644 index 0000000000000..bf2b4e64da5da --- /dev/null +++ b/tests/baselines/reference/contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.symbols @@ -0,0 +1,67 @@ +//// [tests/cases/compiler/contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts] //// + +=== contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts === +class Foo { +>Foo : Symbol(Foo, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts, 0, 0)) + + #foo = "foo"; +>#foo : Symbol(Foo.#foo, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts, 0, 11)) + + doStuff(cb: (arg: string) => void) {} +>doStuff : Symbol(Foo.doStuff, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts, 1, 15)) +>cb : Symbol(cb, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts, 2, 10)) +>arg : Symbol(arg, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts, 2, 15)) +} + +interface FooLike { +>FooLike : Symbol(FooLike, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts, 3, 1)) + + doStuff: (cb: (arg: number) => void) => void; +>doStuff : Symbol(FooLike.doStuff, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts, 5, 19)) +>cb : Symbol(cb, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts, 6, 12)) +>arg : Symbol(arg, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts, 6, 17)) +} + +declare function useIt(arg: Foo | FooLike): void; +>useIt : Symbol(useIt, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts, 7, 1)) +>arg : Symbol(arg, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts, 9, 23)) +>Foo : Symbol(Foo, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts, 0, 0)) +>FooLike : Symbol(FooLike, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts, 3, 1)) + +useIt({ +>useIt : Symbol(useIt, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts, 7, 1)) + + doStuff: (arg) => {}, +>doStuff : Symbol(doStuff, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts, 11, 7)) +>arg : Symbol(arg, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts, 12, 12)) + +}); + +declare function useIt2(arg: Foo): void; +>useIt2 : Symbol(useIt2, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts, 13, 3)) +>arg : Symbol(arg, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts, 15, 24)) +>Foo : Symbol(Foo, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts, 0, 0)) + +useIt2({ +>useIt2 : Symbol(useIt2, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts, 13, 3)) + + doStuff: (arg) => {}, +>doStuff : Symbol(doStuff, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts, 17, 8)) +>arg : Symbol(arg, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts, 18, 12)) + +}); + +declare function useIt3(arg: FooLike): void; +>useIt3 : Symbol(useIt3, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts, 19, 3)) +>arg : Symbol(arg, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts, 21, 24)) +>FooLike : Symbol(FooLike, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts, 3, 1)) + +useIt3({ +>useIt3 : Symbol(useIt3, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts, 19, 3)) + + doStuff: (arg) => {}, +>doStuff : Symbol(doStuff, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts, 23, 8)) +>arg : Symbol(arg, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts, 24, 12)) + +}); + diff --git a/tests/baselines/reference/contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.types b/tests/baselines/reference/contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.types new file mode 100644 index 0000000000000..c9afc7fbcb03a --- /dev/null +++ b/tests/baselines/reference/contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.types @@ -0,0 +1,71 @@ +//// [tests/cases/compiler/contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts] //// + +=== contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts === +class Foo { +>Foo : Foo + + #foo = "foo"; +>#foo : string +>"foo" : "foo" + + doStuff(cb: (arg: string) => void) {} +>doStuff : (cb: (arg: string) => void) => void +>cb : (arg: string) => void +>arg : string +} + +interface FooLike { + doStuff: (cb: (arg: number) => void) => void; +>doStuff : (cb: (arg: number) => void) => void +>cb : (arg: number) => void +>arg : number +} + +declare function useIt(arg: Foo | FooLike): void; +>useIt : (arg: Foo | FooLike) => void +>arg : Foo | FooLike + +useIt({ +>useIt({ doStuff: (arg) => {},}) : void +>useIt : (arg: Foo | FooLike) => void +>{ doStuff: (arg) => {},} : { doStuff: (arg: (arg: number) => void) => void; } + + doStuff: (arg) => {}, +>doStuff : (arg: (arg: number) => void) => void +>(arg) => {} : (arg: (arg: number) => void) => void +>arg : (arg: number) => void + +}); + +declare function useIt2(arg: Foo): void; +>useIt2 : (arg: Foo) => void +>arg : Foo + +useIt2({ +>useIt2({ doStuff: (arg) => {},}) : void +>useIt2 : (arg: Foo) => void +>{ doStuff: (arg) => {},} : { doStuff: (arg: any) => void; } + + doStuff: (arg) => {}, +>doStuff : (arg: any) => void +>(arg) => {} : (arg: any) => void +>arg : any + +}); + +declare function useIt3(arg: FooLike): void; +>useIt3 : (arg: FooLike) => void +>arg : FooLike + +useIt3({ +>useIt3({ doStuff: (arg) => {},}) : void +>useIt3 : (arg: FooLike) => void +>{ doStuff: (arg) => {},} : { doStuff: (arg: (arg: number) => void) => void; } + + doStuff: (arg) => {}, +>doStuff : (arg: (arg: number) => void) => void +>(arg) => {} : (arg: (arg: number) => void) => void +>arg : (arg: number) => void + +}); + diff --git a/tests/baselines/reference/contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.errors.txt b/tests/baselines/reference/contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.errors.txt new file mode 100644 index 0000000000000..b4a2d1a5a5114 --- /dev/null +++ b/tests/baselines/reference/contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.errors.txt @@ -0,0 +1,41 @@ +contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts(18,8): error TS2345: Argument of type '{ doStuff: (arg: any) => void; }' is not assignable to parameter of type 'Foo'. + Property 'foo' is missing in type '{ doStuff: (arg: any) => void; }' but required in type 'Foo'. +contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts(19,13): error TS7006: Parameter 'arg' implicitly has an 'any' type. + + +==== contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts (2 errors) ==== + class Foo { + private foo = "foo"; + doStuff(cb: (arg: string) => void) {} + } + + interface FooLike { + doStuff: (cb: (arg: number) => void) => void; + } + + declare function useIt(arg: Foo | FooLike): void; + + useIt({ + doStuff: (arg) => {}, + }); + + declare function useIt2(arg: Foo): void; + + useIt2({ + ~ + doStuff: (arg) => {}, + ~~~~~~~~~~~~~~~~~~~~~~~ + ~~~ +!!! error TS7006: Parameter 'arg' implicitly has an 'any' type. + }); + ~ +!!! error TS2345: Argument of type '{ doStuff: (arg: any) => void; }' is not assignable to parameter of type 'Foo'. +!!! error TS2345: Property 'foo' is missing in type '{ doStuff: (arg: any) => void; }' but required in type 'Foo'. +!!! related TS2728 contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts:2:11: 'foo' is declared here. + + declare function useIt3(arg: FooLike): void; + + useIt3({ + doStuff: (arg) => {}, + }); + \ No newline at end of file diff --git a/tests/baselines/reference/contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.symbols b/tests/baselines/reference/contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.symbols new file mode 100644 index 0000000000000..f0e4b7df8f065 --- /dev/null +++ b/tests/baselines/reference/contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.symbols @@ -0,0 +1,67 @@ +//// [tests/cases/compiler/contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts] //// + +=== contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts === +class Foo { +>Foo : Symbol(Foo, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts, 0, 0)) + + private foo = "foo"; +>foo : Symbol(Foo.foo, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts, 0, 11)) + + doStuff(cb: (arg: string) => void) {} +>doStuff : Symbol(Foo.doStuff, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts, 1, 22)) +>cb : Symbol(cb, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts, 2, 10)) +>arg : Symbol(arg, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts, 2, 15)) +} + +interface FooLike { +>FooLike : Symbol(FooLike, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts, 3, 1)) + + doStuff: (cb: (arg: number) => void) => void; +>doStuff : Symbol(FooLike.doStuff, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts, 5, 19)) +>cb : Symbol(cb, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts, 6, 12)) +>arg : Symbol(arg, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts, 6, 17)) +} + +declare function useIt(arg: Foo | FooLike): void; +>useIt : Symbol(useIt, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts, 7, 1)) +>arg : Symbol(arg, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts, 9, 23)) +>Foo : Symbol(Foo, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts, 0, 0)) +>FooLike : Symbol(FooLike, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts, 3, 1)) + +useIt({ +>useIt : Symbol(useIt, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts, 7, 1)) + + doStuff: (arg) => {}, +>doStuff : Symbol(doStuff, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts, 11, 7)) +>arg : Symbol(arg, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts, 12, 12)) + +}); + +declare function useIt2(arg: Foo): void; +>useIt2 : Symbol(useIt2, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts, 13, 3)) +>arg : Symbol(arg, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts, 15, 24)) +>Foo : Symbol(Foo, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts, 0, 0)) + +useIt2({ +>useIt2 : Symbol(useIt2, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts, 13, 3)) + + doStuff: (arg) => {}, +>doStuff : Symbol(doStuff, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts, 17, 8)) +>arg : Symbol(arg, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts, 18, 12)) + +}); + +declare function useIt3(arg: FooLike): void; +>useIt3 : Symbol(useIt3, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts, 19, 3)) +>arg : Symbol(arg, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts, 21, 24)) +>FooLike : Symbol(FooLike, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts, 3, 1)) + +useIt3({ +>useIt3 : Symbol(useIt3, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts, 19, 3)) + + doStuff: (arg) => {}, +>doStuff : Symbol(doStuff, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts, 23, 8)) +>arg : Symbol(arg, Decl(contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts, 24, 12)) + +}); + diff --git a/tests/baselines/reference/contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.types b/tests/baselines/reference/contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.types new file mode 100644 index 0000000000000..eed41173a89e7 --- /dev/null +++ b/tests/baselines/reference/contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.types @@ -0,0 +1,71 @@ +//// [tests/cases/compiler/contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts] //// + +=== contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts === +class Foo { +>Foo : Foo + + private foo = "foo"; +>foo : string +>"foo" : "foo" + + doStuff(cb: (arg: string) => void) {} +>doStuff : (cb: (arg: string) => void) => void +>cb : (arg: string) => void +>arg : string +} + +interface FooLike { + doStuff: (cb: (arg: number) => void) => void; +>doStuff : (cb: (arg: number) => void) => void +>cb : (arg: number) => void +>arg : number +} + +declare function useIt(arg: Foo | FooLike): void; +>useIt : (arg: Foo | FooLike) => void +>arg : Foo | FooLike + +useIt({ +>useIt({ doStuff: (arg) => {},}) : void +>useIt : (arg: Foo | FooLike) => void +>{ doStuff: (arg) => {},} : { doStuff: (arg: (arg: number) => void) => void; } + + doStuff: (arg) => {}, +>doStuff : (arg: (arg: number) => void) => void +>(arg) => {} : (arg: (arg: number) => void) => void +>arg : (arg: number) => void + +}); + +declare function useIt2(arg: Foo): void; +>useIt2 : (arg: Foo) => void +>arg : Foo + +useIt2({ +>useIt2({ doStuff: (arg) => {},}) : void +>useIt2 : (arg: Foo) => void +>{ doStuff: (arg) => {},} : { doStuff: (arg: any) => void; } + + doStuff: (arg) => {}, +>doStuff : (arg: any) => void +>(arg) => {} : (arg: any) => void +>arg : any + +}); + +declare function useIt3(arg: FooLike): void; +>useIt3 : (arg: FooLike) => void +>arg : FooLike + +useIt3({ +>useIt3({ doStuff: (arg) => {},}) : void +>useIt3 : (arg: FooLike) => void +>{ doStuff: (arg) => {},} : { doStuff: (arg: (arg: number) => void) => void; } + + doStuff: (arg) => {}, +>doStuff : (arg: (arg: number) => void) => void +>(arg) => {} : (arg: (arg: number) => void) => void +>arg : (arg: number) => void + +}); + diff --git a/tests/cases/compiler/contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts b/tests/cases/compiler/contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts new file mode 100644 index 0000000000000..19ccc3db67174 --- /dev/null +++ b/tests/cases/compiler/contextuallyTypedParametersPositionIncludesClassWithPrivateMember1.ts @@ -0,0 +1,30 @@ +// @strict: true +// @target: esnext +// @noEmit: true + +class Foo { + #foo = "foo"; + doStuff(cb: (arg: string) => void) {} +} + +interface FooLike { + doStuff: (cb: (arg: number) => void) => void; +} + +declare function useIt(arg: Foo | FooLike): void; + +useIt({ + doStuff: (arg) => {}, +}); + +declare function useIt2(arg: Foo): void; + +useIt2({ + doStuff: (arg) => {}, +}); + +declare function useIt3(arg: FooLike): void; + +useIt3({ + doStuff: (arg) => {}, +}); diff --git a/tests/cases/compiler/contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts b/tests/cases/compiler/contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts new file mode 100644 index 0000000000000..d985d05f3900c --- /dev/null +++ b/tests/cases/compiler/contextuallyTypedParametersPositionIncludesClassWithPrivateMember2.ts @@ -0,0 +1,29 @@ +// @strict: true +// @noEmit: true + +class Foo { + private foo = "foo"; + doStuff(cb: (arg: string) => void) {} +} + +interface FooLike { + doStuff: (cb: (arg: number) => void) => void; +} + +declare function useIt(arg: Foo | FooLike): void; + +useIt({ + doStuff: (arg) => {}, +}); + +declare function useIt2(arg: Foo): void; + +useIt2({ + doStuff: (arg) => {}, +}); + +declare function useIt3(arg: FooLike): void; + +useIt3({ + doStuff: (arg) => {}, +}); diff --git a/tests/cases/fourslash/completionsObjectLiteralPositionIncludesClassWithPrivateMember1.ts b/tests/cases/fourslash/completionsObjectLiteralPositionIncludesClassWithPrivateMember1.ts new file mode 100644 index 0000000000000..ce7898246075e --- /dev/null +++ b/tests/cases/fourslash/completionsObjectLiteralPositionIncludesClassWithPrivateMember1.ts @@ -0,0 +1,37 @@ +/// + +// @strict: true + +//// type ExampleInit = { +//// foo: number; +//// }; +//// +//// type ExampleLike = Example | ExampleInit; +//// +//// class Example { +//// static isExample(value: any): value is Example { +//// return #foo in value; +//// } +//// +//// static from(exampleLike: ExampleLike): Example { +//// if (Example.isExample(exampleLike)) { +//// return exampleLike; +//// } +//// return new Example(exampleLike); +//// } +//// +//// readonly #foo: number; +//// +//// constructor({ foo }: ExampleInit) { +//// this.#foo = foo; +//// } +//// } +//// +//// const example = Example.from({ +//// /*1*/ +//// }); + +verify.completions({ + marker: "1", + exact: ["foo"] +}) diff --git a/tests/cases/fourslash/completionsObjectLiteralPositionIncludesClassWithPrivateMember2.ts b/tests/cases/fourslash/completionsObjectLiteralPositionIncludesClassWithPrivateMember2.ts new file mode 100644 index 0000000000000..47a91fc3b1d41 --- /dev/null +++ b/tests/cases/fourslash/completionsObjectLiteralPositionIncludesClassWithPrivateMember2.ts @@ -0,0 +1,37 @@ +/// + +// @strict: true + +//// type ExampleInit = { +//// foo: number; +//// }; +//// +//// type ExampleLike = Example | ExampleInit; +//// +//// class Example { +//// static isExample(value: any): value is Example { +//// return #foo in value; +//// } +//// +//// static from({ exampleLike }: { exampleLike: ExampleLike }): Example { +//// if (Example.isExample(exampleLike)) { +//// return exampleLike; +//// } +//// return new Example(exampleLike); +//// } +//// +//// readonly #foo: number; +//// +//// constructor({ foo }: ExampleInit) { +//// this.#foo = foo; +//// } +//// } +//// +//// const example = Example.from({ +//// exampleLike: { /*1*/ }, +//// }); + +verify.completions({ + marker: "1", + exact: ["foo"] +}) diff --git a/tests/cases/fourslash/completionsObjectLiteralPositionIncludesClassWithPrivateMember3.ts b/tests/cases/fourslash/completionsObjectLiteralPositionIncludesClassWithPrivateMember3.ts new file mode 100644 index 0000000000000..8c178d3f4cd9a --- /dev/null +++ b/tests/cases/fourslash/completionsObjectLiteralPositionIncludesClassWithPrivateMember3.ts @@ -0,0 +1,37 @@ +/// + +// @strict: true + +//// type ExampleInit = { +//// foo: number; +//// }; +//// +//// type ExampleLike = Example | ExampleInit; +//// +//// class Example { +//// static isExample(value: any): value is Example { +//// return 'bar' in value; +//// } +//// +//// static from(exampleLike: ExampleLike): Example { +//// if (Example.isExample(exampleLike)) { +//// return exampleLike; +//// } +//// return new Example(exampleLike); +//// } +//// +//// private bar: number; +//// +//// constructor({ foo }: ExampleInit) { +//// this.bar = foo; +//// } +//// } +//// +//// const example = Example.from({ +//// /*1*/ +//// }); + +verify.completions({ + marker: "1", + exact: ["foo"] +}) diff --git a/tests/cases/fourslash/completionsObjectLiteralPositionIncludesClassWithPrivateMember4.ts b/tests/cases/fourslash/completionsObjectLiteralPositionIncludesClassWithPrivateMember4.ts new file mode 100644 index 0000000000000..8bb0f9dc73fb1 --- /dev/null +++ b/tests/cases/fourslash/completionsObjectLiteralPositionIncludesClassWithPrivateMember4.ts @@ -0,0 +1,37 @@ +/// + +// @strict: true + +//// type ExampleInit = { +//// foo: number; +//// }; +//// +//// type ExampleLike = Example | ExampleInit; +//// +//// class Example { +//// static isExample(value: any): value is Example { +//// return 'bar' in value; +//// } +//// +//// static from({ exampleLike }: { exampleLike: ExampleLike }): Example { +//// if (Example.isExample(exampleLike)) { +//// return exampleLike; +//// } +//// return new Example(exampleLike); +//// } +//// +//// private bar: number; +//// +//// constructor({ foo }: ExampleInit) { +//// this.bar = foo; +//// } +//// } +//// +//// const example = Example.from({ +//// exampleLike: { /*1*/ }, +//// }); + +verify.completions({ + marker: "1", + exact: ["foo"] +})