mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-26 09:19:04 -05:00
Allow exports assignments (#23319)
1. Allow assignment to `exports`. 2. The type of the rhs is not checked against the type of `exports` since they are aliased declarations. To support more complex patterns like `exports = c.name = c`, we may have to treat `c.name` as a declaration. That will be more complicated than this PR.
This commit is contained in:
committed by
GitHub
parent
01b22ff37e
commit
9ceb113ec5
@@ -13882,7 +13882,8 @@ namespace ts {
|
||||
const assignmentKind = getAssignmentTargetKind(node);
|
||||
|
||||
if (assignmentKind) {
|
||||
if (!(localOrExportSymbol.flags & SymbolFlags.Variable)) {
|
||||
if (!(localOrExportSymbol.flags & SymbolFlags.Variable) &&
|
||||
!(isInJavaScriptFile(node) && localOrExportSymbol.flags & SymbolFlags.ValueModule)) {
|
||||
error(node, Diagnostics.Cannot_assign_to_0_because_it_is_not_a_variable, symbolToString(symbol));
|
||||
return unknownType;
|
||||
}
|
||||
@@ -19858,8 +19859,9 @@ namespace ts {
|
||||
// VarExpr = ValueExpr
|
||||
// requires VarExpr to be classified as a reference
|
||||
// A compound assignment furthermore requires VarExpr to be classified as a reference (section 4.1)
|
||||
// and the type of the non - compound operation to be assignable to the type of VarExpr.
|
||||
if (checkReferenceExpression(left, Diagnostics.The_left_hand_side_of_an_assignment_expression_must_be_a_variable_or_a_property_access)) {
|
||||
// and the type of the non-compound operation to be assignable to the type of VarExpr.
|
||||
if (checkReferenceExpression(left, Diagnostics.The_left_hand_side_of_an_assignment_expression_must_be_a_variable_or_a_property_access)
|
||||
&& (!isIdentifier(left) || unescapeLeadingUnderscores(left.escapedText) !== "exports")) {
|
||||
// to avoid cascading errors check assignability only if 'isReference' check succeeded and no errors were reported
|
||||
checkTypeAssignableTo(valueType, leftType, left, /*headMessage*/ undefined);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
tests/cases/conformance/salsa/first.js(1,1): error TS2539: Cannot assign to '"tests/cases/conformance/salsa/first"' because it is not a variable.
|
||||
tests/cases/conformance/salsa/first.js(1,11): error TS2304: Cannot find name 'require'.
|
||||
tests/cases/conformance/salsa/first.js(2,9): error TS2339: Property 'formatters' does not exist on type 'typeof import("tests/cases/conformance/salsa/first")'.
|
||||
tests/cases/conformance/salsa/second.js(1,1): error TS2539: Cannot assign to '"tests/cases/conformance/salsa/second"' because it is not a variable.
|
||||
tests/cases/conformance/salsa/second.js(1,11): error TS2304: Cannot find name 'require'.
|
||||
tests/cases/conformance/salsa/second.js(2,9): error TS2339: Property 'formatters' does not exist on type 'typeof import("tests/cases/conformance/salsa/second")'.
|
||||
|
||||
@@ -9,10 +7,8 @@ tests/cases/conformance/salsa/second.js(2,9): error TS2339: Property 'formatters
|
||||
==== tests/cases/conformance/salsa/mod.js (0 errors) ====
|
||||
// Based on a pattern from adonis
|
||||
exports.formatters = {}
|
||||
==== tests/cases/conformance/salsa/first.js (3 errors) ====
|
||||
==== tests/cases/conformance/salsa/first.js (2 errors) ====
|
||||
exports = require('./mod')
|
||||
~~~~~~~
|
||||
!!! error TS2539: Cannot assign to '"tests/cases/conformance/salsa/first"' because it is not a variable.
|
||||
~~~~~~~
|
||||
!!! error TS2304: Cannot find name 'require'.
|
||||
exports.formatters.j = function (v) {
|
||||
@@ -20,10 +16,8 @@ tests/cases/conformance/salsa/second.js(2,9): error TS2339: Property 'formatters
|
||||
!!! error TS2339: Property 'formatters' does not exist on type 'typeof import("tests/cases/conformance/salsa/first")'.
|
||||
return v
|
||||
}
|
||||
==== tests/cases/conformance/salsa/second.js (3 errors) ====
|
||||
==== tests/cases/conformance/salsa/second.js (2 errors) ====
|
||||
exports = require('./mod')
|
||||
~~~~~~~
|
||||
!!! error TS2539: Cannot assign to '"tests/cases/conformance/salsa/second"' because it is not a variable.
|
||||
~~~~~~~
|
||||
!!! error TS2304: Cannot find name 'require'.
|
||||
exports.formatters.o = function (v) {
|
||||
|
||||
@@ -10,7 +10,7 @@ exports.formatters = {}
|
||||
=== tests/cases/conformance/salsa/first.js ===
|
||||
exports = require('./mod')
|
||||
>exports = require('./mod') : typeof import("tests/cases/conformance/salsa/mod")
|
||||
>exports : any
|
||||
>exports : typeof import("tests/cases/conformance/salsa/first")
|
||||
>require('./mod') : typeof import("tests/cases/conformance/salsa/mod")
|
||||
>require : any
|
||||
>'./mod' : "./mod"
|
||||
@@ -31,7 +31,7 @@ exports.formatters.j = function (v) {
|
||||
=== tests/cases/conformance/salsa/second.js ===
|
||||
exports = require('./mod')
|
||||
>exports = require('./mod') : typeof import("tests/cases/conformance/salsa/mod")
|
||||
>exports : any
|
||||
>exports : typeof import("tests/cases/conformance/salsa/second")
|
||||
>require('./mod') : typeof import("tests/cases/conformance/salsa/mod")
|
||||
>require : any
|
||||
>'./mod' : "./mod"
|
||||
|
||||
@@ -147,7 +147,7 @@ module.exports.func4 = function () { };
|
||||
var multipleDeclarationAlias1 = exports = module.exports;
|
||||
>multipleDeclarationAlias1 : any
|
||||
>exports = module.exports : any
|
||||
>exports : any
|
||||
>exports : typeof import("tests/cases/conformance/salsa/b")
|
||||
>module.exports : any
|
||||
>module : any
|
||||
>exports : any
|
||||
@@ -212,7 +212,7 @@ var multipleDeclarationAlias5 = module.exports = exports = {};
|
||||
>module : any
|
||||
>exports : any
|
||||
>exports = {} : {}
|
||||
>exports : any
|
||||
>exports : typeof import("tests/cases/conformance/salsa/b")
|
||||
>{} : {}
|
||||
|
||||
multipleDeclarationAlias5.func9 = function () { };
|
||||
@@ -225,7 +225,7 @@ multipleDeclarationAlias5.func9 = function () { };
|
||||
var multipleDeclarationAlias6 = exports = module.exports = {};
|
||||
>multipleDeclarationAlias6 : { [x: string]: any; }
|
||||
>exports = module.exports = {} : { [x: string]: any; }
|
||||
>exports : any
|
||||
>exports : typeof import("tests/cases/conformance/salsa/b")
|
||||
>module.exports = {} : { [x: string]: any; }
|
||||
>module.exports : any
|
||||
>module : any
|
||||
@@ -241,7 +241,7 @@ multipleDeclarationAlias6.func10 = function () { };
|
||||
|
||||
exports = module.exports = someOtherVariable = {};
|
||||
>exports = module.exports = someOtherVariable = {} : {}
|
||||
>exports : any
|
||||
>exports : typeof import("tests/cases/conformance/salsa/b")
|
||||
>module.exports = someOtherVariable = {} : {}
|
||||
>module.exports : any
|
||||
>module : any
|
||||
@@ -268,7 +268,7 @@ module.exports.func12 = function () { };
|
||||
|
||||
exports = module.exports = someOtherVariable = {};
|
||||
>exports = module.exports = someOtherVariable = {} : {}
|
||||
>exports : any
|
||||
>exports : typeof import("tests/cases/conformance/salsa/b")
|
||||
>module.exports = someOtherVariable = {} : {}
|
||||
>module.exports : any
|
||||
>module : any
|
||||
@@ -295,7 +295,7 @@ module.exports.func12 = function () { };
|
||||
|
||||
exports = module.exports = {};
|
||||
>exports = module.exports = {} : { [x: string]: any; }
|
||||
>exports : any
|
||||
>exports : typeof import("tests/cases/conformance/salsa/b")
|
||||
>module.exports = {} : { [x: string]: any; }
|
||||
>module.exports : any
|
||||
>module : any
|
||||
@@ -320,7 +320,7 @@ module.exports.func14 = function () { };
|
||||
|
||||
exports = module.exports = {};
|
||||
>exports = module.exports = {} : { [x: string]: any; }
|
||||
>exports : any
|
||||
>exports : typeof import("tests/cases/conformance/salsa/b")
|
||||
>module.exports = {} : { [x: string]: any; }
|
||||
>module.exports : any
|
||||
>module : any
|
||||
@@ -349,7 +349,7 @@ module.exports = exports = {};
|
||||
>module : any
|
||||
>exports : any
|
||||
>exports = {} : {}
|
||||
>exports : any
|
||||
>exports : typeof import("tests/cases/conformance/salsa/b")
|
||||
>{} : {}
|
||||
|
||||
exports.func17 = function () { };
|
||||
|
||||
51
tests/baselines/reference/moduleExportAlias2.symbols
Normal file
51
tests/baselines/reference/moduleExportAlias2.symbols
Normal file
@@ -0,0 +1,51 @@
|
||||
=== tests/cases/conformance/salsa/index.js ===
|
||||
/// <reference path='node.d.ts' />
|
||||
const C = require("./semver")
|
||||
>C : Symbol(C, Decl(index.js, 1, 5))
|
||||
>require : Symbol(require, Decl(node.d.ts, 0, 0))
|
||||
>"./semver" : Symbol("tests/cases/conformance/salsa/semver", Decl(semver.js, 0, 0))
|
||||
|
||||
var two = C.f(1)
|
||||
>two : Symbol(two, Decl(index.js, 2, 3))
|
||||
>C.f : Symbol(f, Decl(semver.js, 1, 28))
|
||||
>C : Symbol(C, Decl(index.js, 1, 5))
|
||||
>f : Symbol(f, Decl(semver.js, 1, 28))
|
||||
|
||||
var c = new C
|
||||
>c : Symbol(c, Decl(index.js, 3, 3))
|
||||
>C : Symbol(C, Decl(index.js, 1, 5))
|
||||
|
||||
=== tests/cases/conformance/salsa/node.d.ts ===
|
||||
declare function require(name: string): any;
|
||||
>require : Symbol(require, Decl(node.d.ts, 0, 0))
|
||||
>name : Symbol(name, Decl(node.d.ts, 0, 25))
|
||||
|
||||
declare var exports: any;
|
||||
>exports : Symbol(exports, Decl(node.d.ts, 1, 11))
|
||||
|
||||
declare var module: { exports: any };
|
||||
>module : Symbol(module, Decl(node.d.ts, 2, 11))
|
||||
>exports : Symbol(exports, Decl(node.d.ts, 2, 21))
|
||||
|
||||
=== tests/cases/conformance/salsa/semver.js ===
|
||||
/// <reference path='node.d.ts' />
|
||||
exports = module.exports = C
|
||||
>exports : Symbol("tests/cases/conformance/salsa/semver", Decl(semver.js, 0, 0))
|
||||
>module.exports : Symbol(exports, Decl(node.d.ts, 2, 21))
|
||||
>module : Symbol(export=, Decl(semver.js, 1, 9))
|
||||
>exports : Symbol(export=, Decl(semver.js, 1, 9))
|
||||
>C : Symbol(C, Decl(semver.js, 2, 22))
|
||||
|
||||
exports.f = n => n + 1
|
||||
>exports.f : Symbol(f, Decl(semver.js, 1, 28))
|
||||
>exports : Symbol(f, Decl(semver.js, 1, 28))
|
||||
>f : Symbol(f, Decl(semver.js, 1, 28))
|
||||
>n : Symbol(n, Decl(semver.js, 2, 11))
|
||||
>n : Symbol(n, Decl(semver.js, 2, 11))
|
||||
|
||||
function C() {
|
||||
>C : Symbol(C, Decl(semver.js, 2, 22))
|
||||
|
||||
this.p = 1
|
||||
>p : Symbol(C.p, Decl(semver.js, 3, 14))
|
||||
}
|
||||
65
tests/baselines/reference/moduleExportAlias2.types
Normal file
65
tests/baselines/reference/moduleExportAlias2.types
Normal file
@@ -0,0 +1,65 @@
|
||||
=== tests/cases/conformance/salsa/index.js ===
|
||||
/// <reference path='node.d.ts' />
|
||||
const C = require("./semver")
|
||||
>C : typeof C
|
||||
>require("./semver") : typeof C
|
||||
>require : (name: string) => any
|
||||
>"./semver" : "./semver"
|
||||
|
||||
var two = C.f(1)
|
||||
>two : any
|
||||
>C.f(1) : any
|
||||
>C.f : (n: any) => any
|
||||
>C : typeof C
|
||||
>f : (n: any) => any
|
||||
>1 : 1
|
||||
|
||||
var c = new C
|
||||
>c : C
|
||||
>new C : C
|
||||
>C : typeof C
|
||||
|
||||
=== tests/cases/conformance/salsa/node.d.ts ===
|
||||
declare function require(name: string): any;
|
||||
>require : (name: string) => any
|
||||
>name : string
|
||||
|
||||
declare var exports: any;
|
||||
>exports : any
|
||||
|
||||
declare var module: { exports: any };
|
||||
>module : { exports: any; }
|
||||
>exports : any
|
||||
|
||||
=== tests/cases/conformance/salsa/semver.js ===
|
||||
/// <reference path='node.d.ts' />
|
||||
exports = module.exports = C
|
||||
>exports = module.exports = C : typeof C
|
||||
>exports : typeof import("tests/cases/conformance/salsa/semver")
|
||||
>module.exports = C : typeof C
|
||||
>module.exports : any
|
||||
>module : { exports: any; }
|
||||
>exports : any
|
||||
>C : typeof C
|
||||
|
||||
exports.f = n => n + 1
|
||||
>exports.f = n => n + 1 : (n: any) => any
|
||||
>exports.f : (n: any) => any
|
||||
>exports : typeof import("tests/cases/conformance/salsa/semver")
|
||||
>f : (n: any) => any
|
||||
>n => n + 1 : (n: any) => any
|
||||
>n : any
|
||||
>n + 1 : any
|
||||
>n : any
|
||||
>1 : 1
|
||||
|
||||
function C() {
|
||||
>C : typeof C
|
||||
|
||||
this.p = 1
|
||||
>this.p = 1 : 1
|
||||
>this.p : any
|
||||
>this : any
|
||||
>p : any
|
||||
>1 : 1
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
tests/cases/conformance/salsa/semver.js(2,1): error TS2539: Cannot assign to '"tests/cases/conformance/salsa/semver"' because it is not a variable.
|
||||
|
||||
|
||||
==== tests/cases/conformance/salsa/index.js (0 errors) ====
|
||||
/// <reference path='./types.d.ts'/>
|
||||
const C = require("./semver")
|
||||
var two = C.f(1)
|
||||
|
||||
==== tests/cases/conformance/salsa/types.d.ts (0 errors) ====
|
||||
declare var require: any;
|
||||
declare var module: any;
|
||||
==== tests/cases/conformance/salsa/semver.js (1 errors) ====
|
||||
/// <reference path='./types.d.ts'/>
|
||||
exports = module.exports = C
|
||||
~~~~~~~
|
||||
!!! error TS2539: Cannot assign to '"tests/cases/conformance/salsa/semver"' because it is not a variable.
|
||||
C.f = n => n + 1
|
||||
function C() {
|
||||
this.p = 1
|
||||
}
|
||||
@@ -25,7 +25,7 @@ declare var module: any;
|
||||
/// <reference path='./types.d.ts'/>
|
||||
exports = module.exports = C
|
||||
>exports = module.exports = C : typeof C
|
||||
>exports : any
|
||||
>exports : typeof import("tests/cases/conformance/salsa/semver")
|
||||
>module.exports = C : typeof C
|
||||
>module.exports : any
|
||||
>module : any
|
||||
|
||||
19
tests/cases/conformance/salsa/moduleExportAlias2.ts
Normal file
19
tests/cases/conformance/salsa/moduleExportAlias2.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
// @checkJs: true
|
||||
// @allowJS: true
|
||||
// @noEmit: true
|
||||
// @Filename: node.d.ts
|
||||
declare function require(name: string): any;
|
||||
declare var exports: any;
|
||||
declare var module: { exports: any };
|
||||
// @Filename: semver.js
|
||||
/// <reference path='node.d.ts' />
|
||||
exports = module.exports = C
|
||||
exports.f = n => n + 1
|
||||
function C() {
|
||||
this.p = 1
|
||||
}
|
||||
// @filename: index.js
|
||||
/// <reference path='node.d.ts' />
|
||||
const C = require("./semver")
|
||||
var two = C.f(1)
|
||||
var c = new C
|
||||
Reference in New Issue
Block a user