diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 80dda6c449dbe..24818abaec4cd 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -3531,7 +3531,7 @@ export function isSpecialPropertyDeclaration(expr: PropertyAccessExpression | El export function setValueDeclaration(symbol: Symbol, node: Declaration): void { const { valueDeclaration } = symbol; if (!valueDeclaration || - !(node.flags & NodeFlags.Ambient && !(valueDeclaration.flags & NodeFlags.Ambient)) && + !(node.flags & NodeFlags.Ambient && !isInJSFile(node) && !(valueDeclaration.flags & NodeFlags.Ambient)) && (isAssignmentDeclaration(valueDeclaration) && !isAssignmentDeclaration(node)) || (valueDeclaration.kind !== node.kind && isEffectiveModuleDeclaration(valueDeclaration))) { // other kinds of value declarations take precedence over modules and assignment declarations diff --git a/tests/baselines/reference/ambientPropertyDeclarationInJs.errors.txt b/tests/baselines/reference/ambientPropertyDeclarationInJs.errors.txt new file mode 100644 index 0000000000000..c23b932b5f8b3 --- /dev/null +++ b/tests/baselines/reference/ambientPropertyDeclarationInJs.errors.txt @@ -0,0 +1,27 @@ +/test.js(3,9): error TS2322: Type '{}' is not assignable to type 'string'. +/test.js(6,5): error TS8009: The 'declare' modifier can only be used in TypeScript files. +/test.js(6,19): error TS8010: Type annotations can only be used in TypeScript files. +/test.js(9,19): error TS2339: Property 'foo' does not exist on type 'string'. + + +==== /test.js (4 errors) ==== + class Foo { + constructor() { + this.prop = {}; + ~~~~~~~~~ +!!! error TS2322: Type '{}' is not assignable to type 'string'. + } + + declare prop: string; + ~~~~~~~ +!!! error TS8009: The 'declare' modifier can only be used in TypeScript files. + ~~~~~~ +!!! error TS8010: Type annotations can only be used in TypeScript files. + + method() { + this.prop.foo + ~~~ +!!! error TS2339: Property 'foo' does not exist on type 'string'. + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/ambientPropertyDeclarationInJs.symbols b/tests/baselines/reference/ambientPropertyDeclarationInJs.symbols new file mode 100644 index 0000000000000..ea7140db784ea --- /dev/null +++ b/tests/baselines/reference/ambientPropertyDeclarationInJs.symbols @@ -0,0 +1,24 @@ +=== /test.js === +class Foo { +>Foo : Symbol(Foo, Decl(test.js, 0, 0)) + + constructor() { + this.prop = {}; +>this.prop : Symbol(Foo.prop, Decl(test.js, 1, 19), Decl(test.js, 3, 5)) +>this : Symbol(Foo, Decl(test.js, 0, 0)) +>prop : Symbol(Foo.prop, Decl(test.js, 1, 19), Decl(test.js, 3, 5)) + } + + declare prop: string; +>prop : Symbol(Foo.prop, Decl(test.js, 1, 19), Decl(test.js, 3, 5)) + + method() { +>method : Symbol(Foo.method, Decl(test.js, 5, 25)) + + this.prop.foo +>this.prop : Symbol(Foo.prop, Decl(test.js, 1, 19), Decl(test.js, 3, 5)) +>this : Symbol(Foo, Decl(test.js, 0, 0)) +>prop : Symbol(Foo.prop, Decl(test.js, 1, 19), Decl(test.js, 3, 5)) + } +} + diff --git a/tests/baselines/reference/ambientPropertyDeclarationInJs.types b/tests/baselines/reference/ambientPropertyDeclarationInJs.types new file mode 100644 index 0000000000000..626075bd0291e --- /dev/null +++ b/tests/baselines/reference/ambientPropertyDeclarationInJs.types @@ -0,0 +1,28 @@ +=== /test.js === +class Foo { +>Foo : Foo + + constructor() { + this.prop = {}; +>this.prop = {} : {} +>this.prop : string +>this : this +>prop : string +>{} : {} + } + + declare prop: string; +>prop : string + + method() { +>method : () => void + + this.prop.foo +>this.prop.foo : any +>this.prop : string +>this : this +>prop : string +>foo : any + } +} + diff --git a/tests/baselines/reference/quickInfoAtPropWithAmbientDeclarationInJs.baseline b/tests/baselines/reference/quickInfoAtPropWithAmbientDeclarationInJs.baseline new file mode 100644 index 0000000000000..f54fc1c08a785 --- /dev/null +++ b/tests/baselines/reference/quickInfoAtPropWithAmbientDeclarationInJs.baseline @@ -0,0 +1,38 @@ +=== /a.js === +// class C { +// constructor() { +// this.prop = ""; +// } +// declare prop: string; +// method() { +// this.prop.foo +// ^^^ +// | ---------------------------------------------------------------------- +// | any +// | ---------------------------------------------------------------------- +// } +// } + +[ + { + "marker": { + "fileName": "/a.js", + "position": 122, + "name": "" + }, + "item": { + "kind": "", + "kindModifiers": "", + "textSpan": { + "start": 119, + "length": 3 + }, + "displayParts": [ + { + "text": "any", + "kind": "keyword" + } + ] + } + } +] \ No newline at end of file diff --git a/tests/cases/compiler/ambientPropertyDeclarationInJs.ts b/tests/cases/compiler/ambientPropertyDeclarationInJs.ts new file mode 100644 index 0000000000000..e7242f63c66ac --- /dev/null +++ b/tests/cases/compiler/ambientPropertyDeclarationInJs.ts @@ -0,0 +1,16 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true +// @filename: /test.js + +class Foo { + constructor() { + this.prop = {}; + } + + declare prop: string; + + method() { + this.prop.foo + } +} diff --git a/tests/cases/fourslash/quickInfoAtPropWithAmbientDeclarationInJs.ts b/tests/cases/fourslash/quickInfoAtPropWithAmbientDeclarationInJs.ts new file mode 100644 index 0000000000000..373b7b19480c2 --- /dev/null +++ b/tests/cases/fourslash/quickInfoAtPropWithAmbientDeclarationInJs.ts @@ -0,0 +1,15 @@ +/// + +// @allowJs: true +// @filename: /a.js +////class C { +//// constructor() { +//// this.prop = ""; +//// } +//// declare prop: string; +//// method() { +//// this.prop.foo/**/ +//// } +////} + +verify.baselineQuickInfo();