diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 34e5000790add..f3d178e9478fa 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2216,7 +2216,22 @@ namespace ts { // An external module with an 'export =' declaration resolves to the target of the 'export =' declaration, // and an external module with no 'export =' declaration resolves to the module itself. function resolveExternalModuleSymbol(moduleSymbol: Symbol, dontResolveAlias?: boolean): Symbol { - return moduleSymbol && getMergedSymbol(resolveSymbol(moduleSymbol.exports.get(InternalSymbolName.ExportEquals), dontResolveAlias)) || moduleSymbol; + return moduleSymbol && getMergedSymbol(resolveSymbol(getCommonJsExportEquals(moduleSymbol), dontResolveAlias)) || moduleSymbol; + } + + function getCommonJsExportEquals(moduleSymbol: Symbol): Symbol { + const exported = moduleSymbol.exports.get(InternalSymbolName.ExportEquals); + if (!exported || !exported.exports || moduleSymbol.exports.size === 1) { + return exported; + } + const merged = cloneSymbol(exported); + moduleSymbol.exports.forEach((s, name) => { + if (name === InternalSymbolName.ExportEquals) return; + if (!merged.exports.has(name)) { + merged.exports.set(name, s); + } + }); + return merged; } // An external module with an 'export =' declaration may be referenced as an ES6 module provided the 'export =' @@ -4350,7 +4365,8 @@ namespace ts { return unknownType; } - if (isPropertyAccessExpression(expression.left) && expression.left.expression.kind === SyntaxKind.ThisKeyword) { + const special = getSpecialPropertyAssignmentKind(expression); + if (special === SpecialPropertyAssignmentKind.ThisProperty) { const thisContainer = getThisContainer(expression, /*includeArrowFunctions*/ false); // Properties defined in a constructor (or javascript constructor function) don't get undefined added. // Function expressions that are assigned to the prototype count as methods. @@ -4380,7 +4396,33 @@ namespace ts { } else if (!jsDocType) { // If we don't have an explicit JSDoc type, get the type from the expression. - const type = getWidenedLiteralType(checkExpressionCached(expression.right)); + let type = getWidenedLiteralType(checkExpressionCached(expression.right)); + + if (getObjectFlags(type) & ObjectFlags.Anonymous && + special === SpecialPropertyAssignmentKind.ModuleExports && + symbol.escapedName === InternalSymbolName.ExportEquals) { + const exportedType = resolveStructuredTypeMembers(type as AnonymousType); + const members = createSymbolTable(); + copyEntries(exportedType.members, members); + symbol.exports.forEach((s, name) => { + if (members.has(name)) { + const exportedMember = exportedType.members.get(name); + const union = createSymbol(s.flags | exportedMember.flags, name); + union.type = getUnionType([getTypeOfSymbol(s), getTypeOfSymbol(exportedMember)]); + members.set(name, union); + } + else { + members.set(name, s); + } + }); + type = createAnonymousType( + exportedType.symbol, + members, + exportedType.callSignatures, + exportedType.constructSignatures, + exportedType.stringIndexInfo, + exportedType.numberIndexInfo); + } let anyedType = type; if (isEmptyArrayLiteralType(type)) { anyedType = anyArrayType; @@ -24568,7 +24610,7 @@ namespace ts { const exportEqualsSymbol = moduleSymbol.exports.get("export=" as __String); if (exportEqualsSymbol && hasExportedMembers(moduleSymbol)) { const declaration = getDeclarationOfAliasSymbol(exportEqualsSymbol) || exportEqualsSymbol.valueDeclaration; - if (!isTopLevelInExternalModuleAugmentation(declaration)) { + if (!isTopLevelInExternalModuleAugmentation(declaration) && !isInJavaScriptFile(declaration)) { error(declaration, Diagnostics.An_export_assignment_cannot_be_used_in_a_module_with_other_exported_elements); } } diff --git a/tests/baselines/reference/moduleExportWithExportPropertyAssignment.errors.txt b/tests/baselines/reference/moduleExportWithExportPropertyAssignment.errors.txt new file mode 100644 index 0000000000000..aab334e77f38c --- /dev/null +++ b/tests/baselines/reference/moduleExportWithExportPropertyAssignment.errors.txt @@ -0,0 +1,20 @@ +tests/cases/conformance/salsa/a.js(4,1): error TS2554: Expected 1 arguments, but got 0. + + +==== tests/cases/conformance/salsa/a.js (1 errors) ==== + /// + var mod1 = require('./mod1') + mod1() + mod1.f() // error, not enough arguments + ~~~~~~~~ +!!! error TS2554: Expected 1 arguments, but got 0. + +==== tests/cases/conformance/salsa/requires.d.ts (0 errors) ==== + declare var module: { exports: any }; + declare function require(name: string): any; +==== tests/cases/conformance/salsa/mod1.js (0 errors) ==== + /// + module.exports = function () { } + /** @param {number} a */ + module.exports.f = function (a) { } + \ No newline at end of file diff --git a/tests/baselines/reference/moduleExportWithExportPropertyAssignment.symbols b/tests/baselines/reference/moduleExportWithExportPropertyAssignment.symbols new file mode 100644 index 0000000000000..c5120a80571e3 --- /dev/null +++ b/tests/baselines/reference/moduleExportWithExportPropertyAssignment.symbols @@ -0,0 +1,39 @@ +=== tests/cases/conformance/salsa/a.js === +/// +var mod1 = require('./mod1') +>mod1 : Symbol(mod1, Decl(a.js, 1, 3)) +>require : Symbol(require, Decl(requires.d.ts, 0, 37)) +>'./mod1' : Symbol("tests/cases/conformance/salsa/mod1", Decl(mod1.js, 0, 0)) + +mod1() +>mod1 : Symbol(mod1, Decl(a.js, 1, 3)) + +mod1.f() // error, not enough arguments +>mod1.f : Symbol(f, Decl(mod1.js, 1, 32)) +>mod1 : Symbol(mod1, Decl(a.js, 1, 3)) +>f : Symbol(f, Decl(mod1.js, 1, 32)) + +=== tests/cases/conformance/salsa/requires.d.ts === +declare var module: { exports: any }; +>module : Symbol(module, Decl(requires.d.ts, 0, 11)) +>exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) + +declare function require(name: string): any; +>require : Symbol(require, Decl(requires.d.ts, 0, 37)) +>name : Symbol(name, Decl(requires.d.ts, 1, 25)) + +=== tests/cases/conformance/salsa/mod1.js === +/// +module.exports = function () { } +>module.exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) +>module : Symbol(export=, Decl(mod1.js, 0, 0)) +>exports : Symbol(export=, Decl(mod1.js, 0, 0)) + +/** @param {number} a */ +module.exports.f = function (a) { } +>module.exports : Symbol(f, Decl(mod1.js, 1, 32)) +>module : Symbol(module, Decl(requires.d.ts, 0, 11)) +>exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) +>f : Symbol(f, Decl(mod1.js, 1, 32)) +>a : Symbol(a, Decl(mod1.js, 3, 29)) + diff --git a/tests/baselines/reference/moduleExportWithExportPropertyAssignment.types b/tests/baselines/reference/moduleExportWithExportPropertyAssignment.types new file mode 100644 index 0000000000000..b7170842c1f39 --- /dev/null +++ b/tests/baselines/reference/moduleExportWithExportPropertyAssignment.types @@ -0,0 +1,47 @@ +=== tests/cases/conformance/salsa/a.js === +/// +var mod1 = require('./mod1') +>mod1 : { (): void; f: (a: number) => void; } +>require('./mod1') : { (): void; f: (a: number) => void; } +>require : (name: string) => any +>'./mod1' : "./mod1" + +mod1() +>mod1() : void +>mod1 : { (): void; f: (a: number) => void; } + +mod1.f() // error, not enough arguments +>mod1.f() : void +>mod1.f : (a: number) => void +>mod1 : { (): void; f: (a: number) => void; } +>f : (a: number) => void + +=== tests/cases/conformance/salsa/requires.d.ts === +declare var module: { exports: any }; +>module : { exports: any; } +>exports : any + +declare function require(name: string): any; +>require : (name: string) => any +>name : string + +=== tests/cases/conformance/salsa/mod1.js === +/// +module.exports = function () { } +>module.exports = function () { } : () => void +>module.exports : any +>module : { exports: any; } +>exports : any +>function () { } : () => void + +/** @param {number} a */ +module.exports.f = function (a) { } +>module.exports.f = function (a) { } : (a: number) => void +>module.exports.f : any +>module.exports : any +>module : { exports: any; } +>exports : any +>f : any +>function (a) { } : (a: number) => void +>a : number + diff --git a/tests/baselines/reference/moduleExportWithExportPropertyAssignment2.errors.txt b/tests/baselines/reference/moduleExportWithExportPropertyAssignment2.errors.txt new file mode 100644 index 0000000000000..66cb517a25be7 --- /dev/null +++ b/tests/baselines/reference/moduleExportWithExportPropertyAssignment2.errors.txt @@ -0,0 +1,19 @@ +tests/cases/conformance/salsa/a.js(4,6): error TS2339: Property 'f' does not exist on type 'number'. + + +==== tests/cases/conformance/salsa/a.js (1 errors) ==== + /// + var mod1 = require('./mod1') + mod1.toFixed(12) + mod1.f() // error, 'f' is not a property on 'number' + ~ +!!! error TS2339: Property 'f' does not exist on type 'number'. + +==== tests/cases/conformance/salsa/requires.d.ts (0 errors) ==== + declare var module: { exports: any }; + declare function require(name: string): any; +==== tests/cases/conformance/salsa/mod1.js (0 errors) ==== + /// + module.exports = 1 + module.exports.f = function () { } + \ No newline at end of file diff --git a/tests/baselines/reference/moduleExportWithExportPropertyAssignment2.symbols b/tests/baselines/reference/moduleExportWithExportPropertyAssignment2.symbols new file mode 100644 index 0000000000000..c9a09bb6a8b99 --- /dev/null +++ b/tests/baselines/reference/moduleExportWithExportPropertyAssignment2.symbols @@ -0,0 +1,37 @@ +=== tests/cases/conformance/salsa/a.js === +/// +var mod1 = require('./mod1') +>mod1 : Symbol(mod1, Decl(a.js, 1, 3)) +>require : Symbol(require, Decl(requires.d.ts, 0, 37)) +>'./mod1' : Symbol("tests/cases/conformance/salsa/mod1", Decl(mod1.js, 0, 0)) + +mod1.toFixed(12) +>mod1.toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) +>mod1 : Symbol(mod1, Decl(a.js, 1, 3)) +>toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) + +mod1.f() // error, 'f' is not a property on 'number' +>mod1 : Symbol(mod1, Decl(a.js, 1, 3)) + +=== tests/cases/conformance/salsa/requires.d.ts === +declare var module: { exports: any }; +>module : Symbol(module, Decl(requires.d.ts, 0, 11)) +>exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) + +declare function require(name: string): any; +>require : Symbol(require, Decl(requires.d.ts, 0, 37)) +>name : Symbol(name, Decl(requires.d.ts, 1, 25)) + +=== tests/cases/conformance/salsa/mod1.js === +/// +module.exports = 1 +>module.exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) +>module : Symbol(export=, Decl(mod1.js, 0, 0)) +>exports : Symbol(export=, Decl(mod1.js, 0, 0)) + +module.exports.f = function () { } +>module.exports : Symbol(f, Decl(mod1.js, 1, 18)) +>module : Symbol(module, Decl(requires.d.ts, 0, 11)) +>exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) +>f : Symbol(f, Decl(mod1.js, 1, 18)) + diff --git a/tests/baselines/reference/moduleExportWithExportPropertyAssignment2.types b/tests/baselines/reference/moduleExportWithExportPropertyAssignment2.types new file mode 100644 index 0000000000000..8af94a05fa5c6 --- /dev/null +++ b/tests/baselines/reference/moduleExportWithExportPropertyAssignment2.types @@ -0,0 +1,48 @@ +=== tests/cases/conformance/salsa/a.js === +/// +var mod1 = require('./mod1') +>mod1 : number +>require('./mod1') : number +>require : (name: string) => any +>'./mod1' : "./mod1" + +mod1.toFixed(12) +>mod1.toFixed(12) : string +>mod1.toFixed : (fractionDigits?: number) => string +>mod1 : number +>toFixed : (fractionDigits?: number) => string +>12 : 12 + +mod1.f() // error, 'f' is not a property on 'number' +>mod1.f() : any +>mod1.f : any +>mod1 : number +>f : any + +=== tests/cases/conformance/salsa/requires.d.ts === +declare var module: { exports: any }; +>module : { exports: any; } +>exports : any + +declare function require(name: string): any; +>require : (name: string) => any +>name : string + +=== tests/cases/conformance/salsa/mod1.js === +/// +module.exports = 1 +>module.exports = 1 : 1 +>module.exports : any +>module : { exports: any; } +>exports : any +>1 : 1 + +module.exports.f = function () { } +>module.exports.f = function () { } : () => void +>module.exports.f : any +>module.exports : any +>module : { exports: any; } +>exports : any +>f : any +>function () { } : () => void + diff --git a/tests/baselines/reference/moduleExportWithExportPropertyAssignment3.errors.txt b/tests/baselines/reference/moduleExportWithExportPropertyAssignment3.errors.txt new file mode 100644 index 0000000000000..bbaed77a0f90c --- /dev/null +++ b/tests/baselines/reference/moduleExportWithExportPropertyAssignment3.errors.txt @@ -0,0 +1,34 @@ +tests/cases/conformance/salsa/a.js(4,17): error TS2339: Property 'toFixed' does not exist on type 'string | number'. + Property 'toFixed' does not exist on type 'string'. +tests/cases/conformance/salsa/a.js(5,16): error TS2339: Property 'toFixed' does not exist on type 'string | number'. + Property 'toFixed' does not exist on type 'string'. + + +==== tests/cases/conformance/salsa/a.js (2 errors) ==== + /// + var mod1 = require('./mod1') + mod1.justExport.toFixed() + mod1.bothBefore.toFixed() // error, 'toFixed' not on 'string | number' + ~~~~~~~ +!!! error TS2339: Property 'toFixed' does not exist on type 'string | number'. +!!! error TS2339: Property 'toFixed' does not exist on type 'string'. + mod1.bothAfter.toFixed() // error, 'toFixed' not on 'string | number' + ~~~~~~~ +!!! error TS2339: Property 'toFixed' does not exist on type 'string | number'. +!!! error TS2339: Property 'toFixed' does not exist on type 'string'. + mod1.justProperty.length + +==== tests/cases/conformance/salsa/requires.d.ts (0 errors) ==== + declare var module: { exports: any }; + declare function require(name: string): any; +==== tests/cases/conformance/salsa/mod1.js (0 errors) ==== + /// + module.exports.bothBefore = 'string' + module.exports = { + justExport: 1, + bothBefore: 2, + bothAfter: 3, + } + module.exports.bothAfter = 'string' + module.exports.justProperty = 'string' + \ No newline at end of file diff --git a/tests/baselines/reference/moduleExportWithExportPropertyAssignment3.symbols b/tests/baselines/reference/moduleExportWithExportPropertyAssignment3.symbols new file mode 100644 index 0000000000000..a84080cc998d8 --- /dev/null +++ b/tests/baselines/reference/moduleExportWithExportPropertyAssignment3.symbols @@ -0,0 +1,74 @@ +=== tests/cases/conformance/salsa/a.js === +/// +var mod1 = require('./mod1') +>mod1 : Symbol(mod1, Decl(a.js, 1, 3)) +>require : Symbol(require, Decl(requires.d.ts, 0, 37)) +>'./mod1' : Symbol("tests/cases/conformance/salsa/mod1", Decl(mod1.js, 0, 0)) + +mod1.justExport.toFixed() +>mod1.justExport.toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) +>mod1.justExport : Symbol(justExport, Decl(mod1.js, 2, 18)) +>mod1 : Symbol(mod1, Decl(a.js, 1, 3)) +>justExport : Symbol(justExport, Decl(mod1.js, 2, 18)) +>toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) + +mod1.bothBefore.toFixed() // error, 'toFixed' not on 'string | number' +>mod1.bothBefore : Symbol(bothBefore) +>mod1 : Symbol(mod1, Decl(a.js, 1, 3)) +>bothBefore : Symbol(bothBefore) + +mod1.bothAfter.toFixed() // error, 'toFixed' not on 'string | number' +>mod1.bothAfter : Symbol(bothAfter) +>mod1 : Symbol(mod1, Decl(a.js, 1, 3)) +>bothAfter : Symbol(bothAfter) + +mod1.justProperty.length +>mod1.justProperty.length : Symbol(String.length, Decl(lib.d.ts, --, --)) +>mod1.justProperty : Symbol(justProperty, Decl(mod1.js, 7, 35)) +>mod1 : Symbol(mod1, Decl(a.js, 1, 3)) +>justProperty : Symbol(justProperty, Decl(mod1.js, 7, 35)) +>length : Symbol(String.length, Decl(lib.d.ts, --, --)) + +=== tests/cases/conformance/salsa/requires.d.ts === +declare var module: { exports: any }; +>module : Symbol(module, Decl(requires.d.ts, 0, 11)) +>exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) + +declare function require(name: string): any; +>require : Symbol(require, Decl(requires.d.ts, 0, 37)) +>name : Symbol(name, Decl(requires.d.ts, 1, 25)) + +=== tests/cases/conformance/salsa/mod1.js === +/// +module.exports.bothBefore = 'string' +>module.exports : Symbol(bothBefore, Decl(mod1.js, 0, 0)) +>module : Symbol(module, Decl(requires.d.ts, 0, 11)) +>exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) +>bothBefore : Symbol(bothBefore, Decl(mod1.js, 0, 0)) + +module.exports = { +>module.exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) +>module : Symbol(export=, Decl(mod1.js, 1, 36)) +>exports : Symbol(export=, Decl(mod1.js, 1, 36)) + + justExport: 1, +>justExport : Symbol(justExport, Decl(mod1.js, 2, 18)) + + bothBefore: 2, +>bothBefore : Symbol(bothBefore, Decl(mod1.js, 3, 18)) + + bothAfter: 3, +>bothAfter : Symbol(bothAfter, Decl(mod1.js, 4, 18)) +} +module.exports.bothAfter = 'string' +>module.exports : Symbol(bothAfter, Decl(mod1.js, 6, 1)) +>module : Symbol(module, Decl(requires.d.ts, 0, 11)) +>exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) +>bothAfter : Symbol(bothAfter, Decl(mod1.js, 6, 1)) + +module.exports.justProperty = 'string' +>module.exports : Symbol(justProperty, Decl(mod1.js, 7, 35)) +>module : Symbol(module, Decl(requires.d.ts, 0, 11)) +>exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) +>justProperty : Symbol(justProperty, Decl(mod1.js, 7, 35)) + diff --git a/tests/baselines/reference/moduleExportWithExportPropertyAssignment3.types b/tests/baselines/reference/moduleExportWithExportPropertyAssignment3.types new file mode 100644 index 0000000000000..4d14bf647fd2c --- /dev/null +++ b/tests/baselines/reference/moduleExportWithExportPropertyAssignment3.types @@ -0,0 +1,96 @@ +=== tests/cases/conformance/salsa/a.js === +/// +var mod1 = require('./mod1') +>mod1 : { [x: string]: any; justExport: number; bothBefore: string | number; bothAfter: string | number; justProperty: string; } +>require('./mod1') : { [x: string]: any; justExport: number; bothBefore: string | number; bothAfter: string | number; justProperty: string; } +>require : (name: string) => any +>'./mod1' : "./mod1" + +mod1.justExport.toFixed() +>mod1.justExport.toFixed() : string +>mod1.justExport.toFixed : (fractionDigits?: number) => string +>mod1.justExport : number +>mod1 : { [x: string]: any; justExport: number; bothBefore: string | number; bothAfter: string | number; justProperty: string; } +>justExport : number +>toFixed : (fractionDigits?: number) => string + +mod1.bothBefore.toFixed() // error, 'toFixed' not on 'string | number' +>mod1.bothBefore.toFixed() : any +>mod1.bothBefore.toFixed : any +>mod1.bothBefore : string | number +>mod1 : { [x: string]: any; justExport: number; bothBefore: string | number; bothAfter: string | number; justProperty: string; } +>bothBefore : string | number +>toFixed : any + +mod1.bothAfter.toFixed() // error, 'toFixed' not on 'string | number' +>mod1.bothAfter.toFixed() : any +>mod1.bothAfter.toFixed : any +>mod1.bothAfter : string | number +>mod1 : { [x: string]: any; justExport: number; bothBefore: string | number; bothAfter: string | number; justProperty: string; } +>bothAfter : string | number +>toFixed : any + +mod1.justProperty.length +>mod1.justProperty.length : number +>mod1.justProperty : string +>mod1 : { [x: string]: any; justExport: number; bothBefore: string | number; bothAfter: string | number; justProperty: string; } +>justProperty : string +>length : number + +=== tests/cases/conformance/salsa/requires.d.ts === +declare var module: { exports: any }; +>module : { exports: any; } +>exports : any + +declare function require(name: string): any; +>require : (name: string) => any +>name : string + +=== tests/cases/conformance/salsa/mod1.js === +/// +module.exports.bothBefore = 'string' +>module.exports.bothBefore = 'string' : "string" +>module.exports.bothBefore : any +>module.exports : any +>module : { exports: any; } +>exports : any +>bothBefore : any +>'string' : "string" + +module.exports = { +>module.exports = { justExport: 1, bothBefore: 2, bothAfter: 3,} : { [x: string]: any; justExport: number; bothBefore: number; bothAfter: number; } +>module.exports : any +>module : { exports: any; } +>exports : any +>{ justExport: 1, bothBefore: 2, bothAfter: 3,} : { [x: string]: any; justExport: number; bothBefore: number; bothAfter: number; } + + justExport: 1, +>justExport : number +>1 : 1 + + bothBefore: 2, +>bothBefore : number +>2 : 2 + + bothAfter: 3, +>bothAfter : number +>3 : 3 +} +module.exports.bothAfter = 'string' +>module.exports.bothAfter = 'string' : "string" +>module.exports.bothAfter : any +>module.exports : any +>module : { exports: any; } +>exports : any +>bothAfter : any +>'string' : "string" + +module.exports.justProperty = 'string' +>module.exports.justProperty = 'string' : "string" +>module.exports.justProperty : any +>module.exports : any +>module : { exports: any; } +>exports : any +>justProperty : any +>'string' : "string" + diff --git a/tests/baselines/reference/moduleExportWithExportPropertyAssignment4.errors.txt b/tests/baselines/reference/moduleExportWithExportPropertyAssignment4.errors.txt new file mode 100644 index 0000000000000..247c29e0ad3af --- /dev/null +++ b/tests/baselines/reference/moduleExportWithExportPropertyAssignment4.errors.txt @@ -0,0 +1,36 @@ +tests/cases/conformance/salsa/a.js(4,17): error TS2339: Property 'toFixed' does not exist on type 'string | number'. + Property 'toFixed' does not exist on type 'string'. +tests/cases/conformance/salsa/a.js(5,16): error TS2339: Property 'toFixed' does not exist on type 'string | number'. + Property 'toFixed' does not exist on type 'string'. + + +==== tests/cases/conformance/salsa/a.js (2 errors) ==== + /// + var mod1 = require('./mod1') + mod1.justExport.toFixed() + mod1.bothBefore.toFixed() // error + ~~~~~~~ +!!! error TS2339: Property 'toFixed' does not exist on type 'string | number'. +!!! error TS2339: Property 'toFixed' does not exist on type 'string'. + mod1.bothAfter.toFixed() + ~~~~~~~ +!!! error TS2339: Property 'toFixed' does not exist on type 'string | number'. +!!! error TS2339: Property 'toFixed' does not exist on type 'string'. + mod1.justProperty.length + +==== tests/cases/conformance/salsa/requires.d.ts (0 errors) ==== + declare var module: { exports: any }; + declare function require(name: string): any; +==== tests/cases/conformance/salsa/mod1.js (0 errors) ==== + /// + module.exports.bothBefore = 'string' + A.justExport = 4 + A.bothBefore = 2 + A.bothAfter = 3 + module.exports = A + function A() { + this.p = 1 + } + module.exports.bothAfter = 'string' + module.exports.justProperty = 'string' + \ No newline at end of file diff --git a/tests/baselines/reference/moduleExportWithExportPropertyAssignment4.symbols b/tests/baselines/reference/moduleExportWithExportPropertyAssignment4.symbols new file mode 100644 index 0000000000000..b62a68c83f3c4 --- /dev/null +++ b/tests/baselines/reference/moduleExportWithExportPropertyAssignment4.symbols @@ -0,0 +1,87 @@ +=== tests/cases/conformance/salsa/a.js === +/// +var mod1 = require('./mod1') +>mod1 : Symbol(mod1, Decl(a.js, 1, 3)) +>require : Symbol(require, Decl(requires.d.ts, 0, 37)) +>'./mod1' : Symbol("tests/cases/conformance/salsa/mod1", Decl(mod1.js, 0, 0)) + +mod1.justExport.toFixed() +>mod1.justExport.toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) +>mod1.justExport : Symbol(A.justExport, Decl(mod1.js, 1, 36)) +>mod1 : Symbol(mod1, Decl(a.js, 1, 3)) +>justExport : Symbol(A.justExport, Decl(mod1.js, 1, 36)) +>toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) + +mod1.bothBefore.toFixed() // error +>mod1.bothBefore : Symbol(bothBefore) +>mod1 : Symbol(mod1, Decl(a.js, 1, 3)) +>bothBefore : Symbol(bothBefore) + +mod1.bothAfter.toFixed() +>mod1.bothAfter : Symbol(bothAfter) +>mod1 : Symbol(mod1, Decl(a.js, 1, 3)) +>bothAfter : Symbol(bothAfter) + +mod1.justProperty.length +>mod1.justProperty.length : Symbol(String.length, Decl(lib.d.ts, --, --)) +>mod1.justProperty : Symbol(justProperty, Decl(mod1.js, 9, 35)) +>mod1 : Symbol(mod1, Decl(a.js, 1, 3)) +>justProperty : Symbol(justProperty, Decl(mod1.js, 9, 35)) +>length : Symbol(String.length, Decl(lib.d.ts, --, --)) + +=== tests/cases/conformance/salsa/requires.d.ts === +declare var module: { exports: any }; +>module : Symbol(module, Decl(requires.d.ts, 0, 11)) +>exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) + +declare function require(name: string): any; +>require : Symbol(require, Decl(requires.d.ts, 0, 37)) +>name : Symbol(name, Decl(requires.d.ts, 1, 25)) + +=== tests/cases/conformance/salsa/mod1.js === +/// +module.exports.bothBefore = 'string' +>module.exports : Symbol(bothBefore, Decl(mod1.js, 0, 0)) +>module : Symbol(module, Decl(requires.d.ts, 0, 11)) +>exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) +>bothBefore : Symbol(bothBefore, Decl(mod1.js, 0, 0)) + +A.justExport = 4 +>A.justExport : Symbol(A.justExport, Decl(mod1.js, 1, 36)) +>A : Symbol(A, Decl(mod1.js, 5, 18)) +>justExport : Symbol(A.justExport, Decl(mod1.js, 1, 36)) + +A.bothBefore = 2 +>A.bothBefore : Symbol(A.bothBefore, Decl(mod1.js, 2, 16)) +>A : Symbol(A, Decl(mod1.js, 5, 18)) +>bothBefore : Symbol(A.bothBefore, Decl(mod1.js, 2, 16)) + +A.bothAfter = 3 +>A.bothAfter : Symbol(A.bothAfter, Decl(mod1.js, 3, 16)) +>A : Symbol(A, Decl(mod1.js, 5, 18)) +>bothAfter : Symbol(A.bothAfter, Decl(mod1.js, 3, 16)) + +module.exports = A +>module.exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) +>module : Symbol(export=, Decl(mod1.js, 4, 15)) +>exports : Symbol(export=, Decl(mod1.js, 4, 15)) +>A : Symbol(A, Decl(mod1.js, 5, 18)) + +function A() { +>A : Symbol(A, Decl(mod1.js, 5, 18)) + + this.p = 1 +>p : Symbol(A.p, Decl(mod1.js, 6, 14)) +} +module.exports.bothAfter = 'string' +>module.exports : Symbol(bothAfter, Decl(mod1.js, 8, 1)) +>module : Symbol(module, Decl(requires.d.ts, 0, 11)) +>exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) +>bothAfter : Symbol(bothAfter, Decl(mod1.js, 8, 1)) + +module.exports.justProperty = 'string' +>module.exports : Symbol(justProperty, Decl(mod1.js, 9, 35)) +>module : Symbol(module, Decl(requires.d.ts, 0, 11)) +>exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) +>justProperty : Symbol(justProperty, Decl(mod1.js, 9, 35)) + diff --git a/tests/baselines/reference/moduleExportWithExportPropertyAssignment4.types b/tests/baselines/reference/moduleExportWithExportPropertyAssignment4.types new file mode 100644 index 0000000000000..f339118bf05ac --- /dev/null +++ b/tests/baselines/reference/moduleExportWithExportPropertyAssignment4.types @@ -0,0 +1,115 @@ +=== tests/cases/conformance/salsa/a.js === +/// +var mod1 = require('./mod1') +>mod1 : typeof A +>require('./mod1') : typeof A +>require : (name: string) => any +>'./mod1' : "./mod1" + +mod1.justExport.toFixed() +>mod1.justExport.toFixed() : string +>mod1.justExport.toFixed : (fractionDigits?: number) => string +>mod1.justExport : number +>mod1 : typeof A +>justExport : number +>toFixed : (fractionDigits?: number) => string + +mod1.bothBefore.toFixed() // error +>mod1.bothBefore.toFixed() : any +>mod1.bothBefore.toFixed : any +>mod1.bothBefore : string | number +>mod1 : typeof A +>bothBefore : string | number +>toFixed : any + +mod1.bothAfter.toFixed() +>mod1.bothAfter.toFixed() : any +>mod1.bothAfter.toFixed : any +>mod1.bothAfter : string | number +>mod1 : typeof A +>bothAfter : string | number +>toFixed : any + +mod1.justProperty.length +>mod1.justProperty.length : number +>mod1.justProperty : string +>mod1 : typeof A +>justProperty : string +>length : number + +=== tests/cases/conformance/salsa/requires.d.ts === +declare var module: { exports: any }; +>module : { exports: any; } +>exports : any + +declare function require(name: string): any; +>require : (name: string) => any +>name : string + +=== tests/cases/conformance/salsa/mod1.js === +/// +module.exports.bothBefore = 'string' +>module.exports.bothBefore = 'string' : "string" +>module.exports.bothBefore : any +>module.exports : any +>module : { exports: any; } +>exports : any +>bothBefore : any +>'string' : "string" + +A.justExport = 4 +>A.justExport = 4 : 4 +>A.justExport : number +>A : typeof A +>justExport : number +>4 : 4 + +A.bothBefore = 2 +>A.bothBefore = 2 : 2 +>A.bothBefore : number +>A : typeof A +>bothBefore : number +>2 : 2 + +A.bothAfter = 3 +>A.bothAfter = 3 : 3 +>A.bothAfter : number +>A : typeof A +>bothAfter : number +>3 : 3 + +module.exports = A +>module.exports = A : typeof A +>module.exports : any +>module : { exports: any; } +>exports : any +>A : typeof A + +function A() { +>A : typeof A + + this.p = 1 +>this.p = 1 : 1 +>this.p : any +>this : any +>p : any +>1 : 1 +} +module.exports.bothAfter = 'string' +>module.exports.bothAfter = 'string' : "string" +>module.exports.bothAfter : any +>module.exports : any +>module : { exports: any; } +>exports : any +>bothAfter : any +>'string' : "string" + +module.exports.justProperty = 'string' +>module.exports.justProperty = 'string' : "string" +>module.exports.justProperty : any +>module.exports : any +>module : { exports: any; } +>exports : any +>justProperty : any +>'string' : "string" + diff --git a/tests/cases/conformance/salsa/moduleExportWithExportPropertyAssignment.ts b/tests/cases/conformance/salsa/moduleExportWithExportPropertyAssignment.ts new file mode 100644 index 0000000000000..926a4cadf08f7 --- /dev/null +++ b/tests/cases/conformance/salsa/moduleExportWithExportPropertyAssignment.ts @@ -0,0 +1,17 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @Filename: requires.d.ts +declare var module: { exports: any }; +declare function require(name: string): any; +// @Filename: mod1.js +/// +module.exports = function () { } +/** @param {number} a */ +module.exports.f = function (a) { } + +// @Filename: a.js +/// +var mod1 = require('./mod1') +mod1() +mod1.f() // error, not enough arguments diff --git a/tests/cases/conformance/salsa/moduleExportWithExportPropertyAssignment2.ts b/tests/cases/conformance/salsa/moduleExportWithExportPropertyAssignment2.ts new file mode 100644 index 0000000000000..ae3d770b0a412 --- /dev/null +++ b/tests/cases/conformance/salsa/moduleExportWithExportPropertyAssignment2.ts @@ -0,0 +1,16 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @Filename: requires.d.ts +declare var module: { exports: any }; +declare function require(name: string): any; +// @Filename: mod1.js +/// +module.exports = 1 +module.exports.f = function () { } + +// @Filename: a.js +/// +var mod1 = require('./mod1') +mod1.toFixed(12) +mod1.f() // error, 'f' is not a property on 'number' diff --git a/tests/cases/conformance/salsa/moduleExportWithExportPropertyAssignment3.ts b/tests/cases/conformance/salsa/moduleExportWithExportPropertyAssignment3.ts new file mode 100644 index 0000000000000..673858bb13e4f --- /dev/null +++ b/tests/cases/conformance/salsa/moduleExportWithExportPropertyAssignment3.ts @@ -0,0 +1,24 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @Filename: requires.d.ts +declare var module: { exports: any }; +declare function require(name: string): any; +// @Filename: mod1.js +/// +module.exports.bothBefore = 'string' +module.exports = { + justExport: 1, + bothBefore: 2, + bothAfter: 3, +} +module.exports.bothAfter = 'string' +module.exports.justProperty = 'string' + +// @Filename: a.js +/// +var mod1 = require('./mod1') +mod1.justExport.toFixed() +mod1.bothBefore.toFixed() // error, 'toFixed' not on 'string | number' +mod1.bothAfter.toFixed() // error, 'toFixed' not on 'string | number' +mod1.justProperty.length diff --git a/tests/cases/conformance/salsa/moduleExportWithExportPropertyAssignment4.ts b/tests/cases/conformance/salsa/moduleExportWithExportPropertyAssignment4.ts new file mode 100644 index 0000000000000..90b54095cbf11 --- /dev/null +++ b/tests/cases/conformance/salsa/moduleExportWithExportPropertyAssignment4.ts @@ -0,0 +1,26 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @Filename: requires.d.ts +declare var module: { exports: any }; +declare function require(name: string): any; +// @Filename: mod1.js +/// +module.exports.bothBefore = 'string' +A.justExport = 4 +A.bothBefore = 2 +A.bothAfter = 3 +module.exports = A +function A() { + this.p = 1 +} +module.exports.bothAfter = 'string' +module.exports.justProperty = 'string' + +// @Filename: a.js +/// +var mod1 = require('./mod1') +mod1.justExport.toFixed() +mod1.bothBefore.toFixed() // error +mod1.bothAfter.toFixed() +mod1.justProperty.length