Class property doesn't exist
up vote
-1
down vote
favorite
I have been bugging on an issue, unable to find the solution. I have simplified the code to a minimum, but I still can't figure it out.
I have set up 2 basic projects with the same configuration for Babel and Typescript. One of my project is actually a module, which I import in the other project. Both of my projects are coded in Typescript, but each of them are transpiled to JS before I run them.
Both projects have the following Babel 7 configuration:
// babel.config.js
module.exports = function( api ) {
api.cache( () => process.env.NODE_ENV );
const presets = [
[
"@babel/env",
{
targets: {
node: "10",
browsers: "> 0.25%, not dead" // without this line, Babel doesn't transform the class and it works.
},
useBuiltIns: "usage",
}
],
"@babel/preset-typescript"
];
const plugins = [
// same result with or without this plugin
// the value of loose doesn't change anything
[ "@babel/plugin-proposal-class-properties", { loose: false } ]
];
return {
presets,
plugins,
};
};
Both projects have the following Typescript configuration:
// tsconfig.json
{
"compilerOptions": {
"target": "ES5", // I tried multiples values for this one
"module": "commonjs",
"allowJs": true,
"noEmit": true,
"esModuleInterop": true
}
}
My first test is to compile my class and run it without any module.
This is my source code:
//{ProjectRoot}/src/main.ts
class MOD {
public name:string;
constructor() {
this.name = "Foo";
}
getName():string {
return this.name;
}
}
const mod = new MOD();
console.log(MOD) // Output: [Function: MOD]
console.log(mod) // Output: MOD { name: 'Foo' }
console.log(mod.getName())// Output: Foo
I compile and run this source code by running:
tsc && babel ./src --out-dir dist -x .js,.ts -D --verbose --delete-dir-on-start && node dist/main
Everything runs fine, and I get the expected output in my terminal.
When I look at dist/main.js, I can see that the class has been completely rewritten by the compiler.
//{ProjectRoot}/dist/main.js
//... some code added by Babel ...
var MOD =
/*#__PURE__*/
function () {
function MOD() {
_classCallCheck(this, MOD);
_defineProperty(this, "name", void 0);
this.name = "Foo";
}
_createClass(MOD, [{
key: "getName",
value: function getName() {
return this.name;
}
}]);
return MOD;
}();
If I remove the browsers: "> 0.25%, not dead"
in the Babel configuration, the compiler only adds the _defineProperty function, but keeps the rest of the code as is.
I then moved the same code to another projects, which simulates a NPM module (but in another directory, outside of the project root).
The source code of the module is:
// {moduleRoot}/src/main.ts
class MOD {
constructor() {
this.name = "Foo";
}
getName() {
return this.name;
}
}
module.exports = MOD;
The module is compiled using the same command as above.
Then in my project, I modified the source as follows:
//{ProjectRoot}/src/main.ts
//const Mod = require("../../module/dist/main"); // Works with require()
import Mod from "../../module/dist/main"; // Doesn't work with import
const mod = new Mod();
console.log(MOD) // Output: [Function: MOD]
console.log(mod) // Output: MOD { name: 'Foo' }
console.log(mod.getName())// Output: Foo
Again, it works great. I then replace the require()
by the import
, and things don't work anymore.
If I compile without doing the type check, then I get the correct output, meaning that Node can interpret my code.
However Typescript gives me the following error when doing the type-check:
src/main.ts:7:17 - error TS2339: Property 'getName' does not exist on type 'MOD'.
7 console.log(mod.getName())
I don't understand why the result is impacted by the way I import the module.
It seems to me that the Typescript compiler is not able to resolve the module correctly.
I have created a Gist with the source codes and the compiled code.
Any idea?
Thanks a lot!
typescript
add a comment |
up vote
-1
down vote
favorite
I have been bugging on an issue, unable to find the solution. I have simplified the code to a minimum, but I still can't figure it out.
I have set up 2 basic projects with the same configuration for Babel and Typescript. One of my project is actually a module, which I import in the other project. Both of my projects are coded in Typescript, but each of them are transpiled to JS before I run them.
Both projects have the following Babel 7 configuration:
// babel.config.js
module.exports = function( api ) {
api.cache( () => process.env.NODE_ENV );
const presets = [
[
"@babel/env",
{
targets: {
node: "10",
browsers: "> 0.25%, not dead" // without this line, Babel doesn't transform the class and it works.
},
useBuiltIns: "usage",
}
],
"@babel/preset-typescript"
];
const plugins = [
// same result with or without this plugin
// the value of loose doesn't change anything
[ "@babel/plugin-proposal-class-properties", { loose: false } ]
];
return {
presets,
plugins,
};
};
Both projects have the following Typescript configuration:
// tsconfig.json
{
"compilerOptions": {
"target": "ES5", // I tried multiples values for this one
"module": "commonjs",
"allowJs": true,
"noEmit": true,
"esModuleInterop": true
}
}
My first test is to compile my class and run it without any module.
This is my source code:
//{ProjectRoot}/src/main.ts
class MOD {
public name:string;
constructor() {
this.name = "Foo";
}
getName():string {
return this.name;
}
}
const mod = new MOD();
console.log(MOD) // Output: [Function: MOD]
console.log(mod) // Output: MOD { name: 'Foo' }
console.log(mod.getName())// Output: Foo
I compile and run this source code by running:
tsc && babel ./src --out-dir dist -x .js,.ts -D --verbose --delete-dir-on-start && node dist/main
Everything runs fine, and I get the expected output in my terminal.
When I look at dist/main.js, I can see that the class has been completely rewritten by the compiler.
//{ProjectRoot}/dist/main.js
//... some code added by Babel ...
var MOD =
/*#__PURE__*/
function () {
function MOD() {
_classCallCheck(this, MOD);
_defineProperty(this, "name", void 0);
this.name = "Foo";
}
_createClass(MOD, [{
key: "getName",
value: function getName() {
return this.name;
}
}]);
return MOD;
}();
If I remove the browsers: "> 0.25%, not dead"
in the Babel configuration, the compiler only adds the _defineProperty function, but keeps the rest of the code as is.
I then moved the same code to another projects, which simulates a NPM module (but in another directory, outside of the project root).
The source code of the module is:
// {moduleRoot}/src/main.ts
class MOD {
constructor() {
this.name = "Foo";
}
getName() {
return this.name;
}
}
module.exports = MOD;
The module is compiled using the same command as above.
Then in my project, I modified the source as follows:
//{ProjectRoot}/src/main.ts
//const Mod = require("../../module/dist/main"); // Works with require()
import Mod from "../../module/dist/main"; // Doesn't work with import
const mod = new Mod();
console.log(MOD) // Output: [Function: MOD]
console.log(mod) // Output: MOD { name: 'Foo' }
console.log(mod.getName())// Output: Foo
Again, it works great. I then replace the require()
by the import
, and things don't work anymore.
If I compile without doing the type check, then I get the correct output, meaning that Node can interpret my code.
However Typescript gives me the following error when doing the type-check:
src/main.ts:7:17 - error TS2339: Property 'getName' does not exist on type 'MOD'.
7 console.log(mod.getName())
I don't understand why the result is impacted by the way I import the module.
It seems to me that the Typescript compiler is not able to resolve the module correctly.
I have created a Gist with the source codes and the compiled code.
Any idea?
Thanks a lot!
typescript
add a comment |
up vote
-1
down vote
favorite
up vote
-1
down vote
favorite
I have been bugging on an issue, unable to find the solution. I have simplified the code to a minimum, but I still can't figure it out.
I have set up 2 basic projects with the same configuration for Babel and Typescript. One of my project is actually a module, which I import in the other project. Both of my projects are coded in Typescript, but each of them are transpiled to JS before I run them.
Both projects have the following Babel 7 configuration:
// babel.config.js
module.exports = function( api ) {
api.cache( () => process.env.NODE_ENV );
const presets = [
[
"@babel/env",
{
targets: {
node: "10",
browsers: "> 0.25%, not dead" // without this line, Babel doesn't transform the class and it works.
},
useBuiltIns: "usage",
}
],
"@babel/preset-typescript"
];
const plugins = [
// same result with or without this plugin
// the value of loose doesn't change anything
[ "@babel/plugin-proposal-class-properties", { loose: false } ]
];
return {
presets,
plugins,
};
};
Both projects have the following Typescript configuration:
// tsconfig.json
{
"compilerOptions": {
"target": "ES5", // I tried multiples values for this one
"module": "commonjs",
"allowJs": true,
"noEmit": true,
"esModuleInterop": true
}
}
My first test is to compile my class and run it without any module.
This is my source code:
//{ProjectRoot}/src/main.ts
class MOD {
public name:string;
constructor() {
this.name = "Foo";
}
getName():string {
return this.name;
}
}
const mod = new MOD();
console.log(MOD) // Output: [Function: MOD]
console.log(mod) // Output: MOD { name: 'Foo' }
console.log(mod.getName())// Output: Foo
I compile and run this source code by running:
tsc && babel ./src --out-dir dist -x .js,.ts -D --verbose --delete-dir-on-start && node dist/main
Everything runs fine, and I get the expected output in my terminal.
When I look at dist/main.js, I can see that the class has been completely rewritten by the compiler.
//{ProjectRoot}/dist/main.js
//... some code added by Babel ...
var MOD =
/*#__PURE__*/
function () {
function MOD() {
_classCallCheck(this, MOD);
_defineProperty(this, "name", void 0);
this.name = "Foo";
}
_createClass(MOD, [{
key: "getName",
value: function getName() {
return this.name;
}
}]);
return MOD;
}();
If I remove the browsers: "> 0.25%, not dead"
in the Babel configuration, the compiler only adds the _defineProperty function, but keeps the rest of the code as is.
I then moved the same code to another projects, which simulates a NPM module (but in another directory, outside of the project root).
The source code of the module is:
// {moduleRoot}/src/main.ts
class MOD {
constructor() {
this.name = "Foo";
}
getName() {
return this.name;
}
}
module.exports = MOD;
The module is compiled using the same command as above.
Then in my project, I modified the source as follows:
//{ProjectRoot}/src/main.ts
//const Mod = require("../../module/dist/main"); // Works with require()
import Mod from "../../module/dist/main"; // Doesn't work with import
const mod = new Mod();
console.log(MOD) // Output: [Function: MOD]
console.log(mod) // Output: MOD { name: 'Foo' }
console.log(mod.getName())// Output: Foo
Again, it works great. I then replace the require()
by the import
, and things don't work anymore.
If I compile without doing the type check, then I get the correct output, meaning that Node can interpret my code.
However Typescript gives me the following error when doing the type-check:
src/main.ts:7:17 - error TS2339: Property 'getName' does not exist on type 'MOD'.
7 console.log(mod.getName())
I don't understand why the result is impacted by the way I import the module.
It seems to me that the Typescript compiler is not able to resolve the module correctly.
I have created a Gist with the source codes and the compiled code.
Any idea?
Thanks a lot!
typescript
I have been bugging on an issue, unable to find the solution. I have simplified the code to a minimum, but I still can't figure it out.
I have set up 2 basic projects with the same configuration for Babel and Typescript. One of my project is actually a module, which I import in the other project. Both of my projects are coded in Typescript, but each of them are transpiled to JS before I run them.
Both projects have the following Babel 7 configuration:
// babel.config.js
module.exports = function( api ) {
api.cache( () => process.env.NODE_ENV );
const presets = [
[
"@babel/env",
{
targets: {
node: "10",
browsers: "> 0.25%, not dead" // without this line, Babel doesn't transform the class and it works.
},
useBuiltIns: "usage",
}
],
"@babel/preset-typescript"
];
const plugins = [
// same result with or without this plugin
// the value of loose doesn't change anything
[ "@babel/plugin-proposal-class-properties", { loose: false } ]
];
return {
presets,
plugins,
};
};
Both projects have the following Typescript configuration:
// tsconfig.json
{
"compilerOptions": {
"target": "ES5", // I tried multiples values for this one
"module": "commonjs",
"allowJs": true,
"noEmit": true,
"esModuleInterop": true
}
}
My first test is to compile my class and run it without any module.
This is my source code:
//{ProjectRoot}/src/main.ts
class MOD {
public name:string;
constructor() {
this.name = "Foo";
}
getName():string {
return this.name;
}
}
const mod = new MOD();
console.log(MOD) // Output: [Function: MOD]
console.log(mod) // Output: MOD { name: 'Foo' }
console.log(mod.getName())// Output: Foo
I compile and run this source code by running:
tsc && babel ./src --out-dir dist -x .js,.ts -D --verbose --delete-dir-on-start && node dist/main
Everything runs fine, and I get the expected output in my terminal.
When I look at dist/main.js, I can see that the class has been completely rewritten by the compiler.
//{ProjectRoot}/dist/main.js
//... some code added by Babel ...
var MOD =
/*#__PURE__*/
function () {
function MOD() {
_classCallCheck(this, MOD);
_defineProperty(this, "name", void 0);
this.name = "Foo";
}
_createClass(MOD, [{
key: "getName",
value: function getName() {
return this.name;
}
}]);
return MOD;
}();
If I remove the browsers: "> 0.25%, not dead"
in the Babel configuration, the compiler only adds the _defineProperty function, but keeps the rest of the code as is.
I then moved the same code to another projects, which simulates a NPM module (but in another directory, outside of the project root).
The source code of the module is:
// {moduleRoot}/src/main.ts
class MOD {
constructor() {
this.name = "Foo";
}
getName() {
return this.name;
}
}
module.exports = MOD;
The module is compiled using the same command as above.
Then in my project, I modified the source as follows:
//{ProjectRoot}/src/main.ts
//const Mod = require("../../module/dist/main"); // Works with require()
import Mod from "../../module/dist/main"; // Doesn't work with import
const mod = new Mod();
console.log(MOD) // Output: [Function: MOD]
console.log(mod) // Output: MOD { name: 'Foo' }
console.log(mod.getName())// Output: Foo
Again, it works great. I then replace the require()
by the import
, and things don't work anymore.
If I compile without doing the type check, then I get the correct output, meaning that Node can interpret my code.
However Typescript gives me the following error when doing the type-check:
src/main.ts:7:17 - error TS2339: Property 'getName' does not exist on type 'MOD'.
7 console.log(mod.getName())
I don't understand why the result is impacted by the way I import the module.
It seems to me that the Typescript compiler is not able to resolve the module correctly.
I have created a Gist with the source codes and the compiled code.
Any idea?
Thanks a lot!
typescript
typescript
edited Nov 11 at 3:09
asked Nov 11 at 2:19
h-Reser
32
32
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
up vote
0
down vote
accepted
Since the project is importing module/dist/main
, and only a .js
file exists at that path, the only type information the TypeScript compiler has for that import is what it can extract from main.js
, which in general is going to be incomplete. What you should probably do is have tsc
on the module generate .d.ts
files alongside the .js
files. Then tsc
on the project will use the .d.ts
files. E.g., change module/tsconfig.json
to the following:
{
"compilerOptions": {
"target": "ES5",
"module": "commonjs",
"rootDir": "src",
"outDir": "dist",
"declaration": true,
"emitDeclarationOnly": true,
"esModuleInterop": true
}
}
(Note that allowJs
has to be removed because it is incompatible with declaration
. If you needed allowJs
, please explain your scenario and I'll try to help you solve it.) And compile the module with this command:
rm -rf dist && tsc && babel ./src --out-dir dist -x .js,.ts -D --verbose
You'll also have to change the export at the end of module/src/main.ts
to:
export default MOD;
because the TypeScript compiler does not recognize assignments to module.exports
in a .ts
file and Babel does not support export = MOD
. This should work as long as all consumers of the module use a default import. (Again, if you need to support consumers that do a plain require
, please explain your scenario and I'll see what I can do.)
Update
If you need an export assignment, since your .ts
file will need to say export = MOD
and Babel doesn't accept that, the only solution I can find is to run Babel on the JavaScript generated by tsc
in which the export = MOD
will have been translated to module.exports = MOD
. In an example configuration, module/tsconfig.json
is:
{
"compilerOptions": {
"target": "ES6",
"module": "commonjs",
"rootDir": "src",
"outDir": "ts-out",
"declarationDir": "dist",
"declaration": true,
"esModuleInterop": true
}
}
and the build command is:
rm -rf dist ts-out && tsc && babel ./ts-out --out-dir dist -x .js,.ts -D --verbose
(This is assuming you have some reason to use Babel at all rather than using the JavaScript output of tsc
directly.)
Yes, your solution works indeed. But as you said it no longer works withrequire
, which is something that I want. I want anyone to be able to use my module, whether it's with CommonJS or ES Modules.When I download a package on NPM, I can usually use both systems. Take one example, Express, they use module.exports, which is why I tried this way. I'm surprised that it doesn't work with my module. I don't really understand the difference.
– h-Reser
Nov 11 at 4:23
See the updated answer for how to makerequire
work.
– Matt McCutchen
Nov 11 at 4:43
I managed to do it. I think I was lacking some comprehension of the CommonJS and ES modules. Thanks a lot for looking into that, you were a big help :)
– h-Reser
Nov 11 at 20:08
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
accepted
Since the project is importing module/dist/main
, and only a .js
file exists at that path, the only type information the TypeScript compiler has for that import is what it can extract from main.js
, which in general is going to be incomplete. What you should probably do is have tsc
on the module generate .d.ts
files alongside the .js
files. Then tsc
on the project will use the .d.ts
files. E.g., change module/tsconfig.json
to the following:
{
"compilerOptions": {
"target": "ES5",
"module": "commonjs",
"rootDir": "src",
"outDir": "dist",
"declaration": true,
"emitDeclarationOnly": true,
"esModuleInterop": true
}
}
(Note that allowJs
has to be removed because it is incompatible with declaration
. If you needed allowJs
, please explain your scenario and I'll try to help you solve it.) And compile the module with this command:
rm -rf dist && tsc && babel ./src --out-dir dist -x .js,.ts -D --verbose
You'll also have to change the export at the end of module/src/main.ts
to:
export default MOD;
because the TypeScript compiler does not recognize assignments to module.exports
in a .ts
file and Babel does not support export = MOD
. This should work as long as all consumers of the module use a default import. (Again, if you need to support consumers that do a plain require
, please explain your scenario and I'll see what I can do.)
Update
If you need an export assignment, since your .ts
file will need to say export = MOD
and Babel doesn't accept that, the only solution I can find is to run Babel on the JavaScript generated by tsc
in which the export = MOD
will have been translated to module.exports = MOD
. In an example configuration, module/tsconfig.json
is:
{
"compilerOptions": {
"target": "ES6",
"module": "commonjs",
"rootDir": "src",
"outDir": "ts-out",
"declarationDir": "dist",
"declaration": true,
"esModuleInterop": true
}
}
and the build command is:
rm -rf dist ts-out && tsc && babel ./ts-out --out-dir dist -x .js,.ts -D --verbose
(This is assuming you have some reason to use Babel at all rather than using the JavaScript output of tsc
directly.)
Yes, your solution works indeed. But as you said it no longer works withrequire
, which is something that I want. I want anyone to be able to use my module, whether it's with CommonJS or ES Modules.When I download a package on NPM, I can usually use both systems. Take one example, Express, they use module.exports, which is why I tried this way. I'm surprised that it doesn't work with my module. I don't really understand the difference.
– h-Reser
Nov 11 at 4:23
See the updated answer for how to makerequire
work.
– Matt McCutchen
Nov 11 at 4:43
I managed to do it. I think I was lacking some comprehension of the CommonJS and ES modules. Thanks a lot for looking into that, you were a big help :)
– h-Reser
Nov 11 at 20:08
add a comment |
up vote
0
down vote
accepted
Since the project is importing module/dist/main
, and only a .js
file exists at that path, the only type information the TypeScript compiler has for that import is what it can extract from main.js
, which in general is going to be incomplete. What you should probably do is have tsc
on the module generate .d.ts
files alongside the .js
files. Then tsc
on the project will use the .d.ts
files. E.g., change module/tsconfig.json
to the following:
{
"compilerOptions": {
"target": "ES5",
"module": "commonjs",
"rootDir": "src",
"outDir": "dist",
"declaration": true,
"emitDeclarationOnly": true,
"esModuleInterop": true
}
}
(Note that allowJs
has to be removed because it is incompatible with declaration
. If you needed allowJs
, please explain your scenario and I'll try to help you solve it.) And compile the module with this command:
rm -rf dist && tsc && babel ./src --out-dir dist -x .js,.ts -D --verbose
You'll also have to change the export at the end of module/src/main.ts
to:
export default MOD;
because the TypeScript compiler does not recognize assignments to module.exports
in a .ts
file and Babel does not support export = MOD
. This should work as long as all consumers of the module use a default import. (Again, if you need to support consumers that do a plain require
, please explain your scenario and I'll see what I can do.)
Update
If you need an export assignment, since your .ts
file will need to say export = MOD
and Babel doesn't accept that, the only solution I can find is to run Babel on the JavaScript generated by tsc
in which the export = MOD
will have been translated to module.exports = MOD
. In an example configuration, module/tsconfig.json
is:
{
"compilerOptions": {
"target": "ES6",
"module": "commonjs",
"rootDir": "src",
"outDir": "ts-out",
"declarationDir": "dist",
"declaration": true,
"esModuleInterop": true
}
}
and the build command is:
rm -rf dist ts-out && tsc && babel ./ts-out --out-dir dist -x .js,.ts -D --verbose
(This is assuming you have some reason to use Babel at all rather than using the JavaScript output of tsc
directly.)
Yes, your solution works indeed. But as you said it no longer works withrequire
, which is something that I want. I want anyone to be able to use my module, whether it's with CommonJS or ES Modules.When I download a package on NPM, I can usually use both systems. Take one example, Express, they use module.exports, which is why I tried this way. I'm surprised that it doesn't work with my module. I don't really understand the difference.
– h-Reser
Nov 11 at 4:23
See the updated answer for how to makerequire
work.
– Matt McCutchen
Nov 11 at 4:43
I managed to do it. I think I was lacking some comprehension of the CommonJS and ES modules. Thanks a lot for looking into that, you were a big help :)
– h-Reser
Nov 11 at 20:08
add a comment |
up vote
0
down vote
accepted
up vote
0
down vote
accepted
Since the project is importing module/dist/main
, and only a .js
file exists at that path, the only type information the TypeScript compiler has for that import is what it can extract from main.js
, which in general is going to be incomplete. What you should probably do is have tsc
on the module generate .d.ts
files alongside the .js
files. Then tsc
on the project will use the .d.ts
files. E.g., change module/tsconfig.json
to the following:
{
"compilerOptions": {
"target": "ES5",
"module": "commonjs",
"rootDir": "src",
"outDir": "dist",
"declaration": true,
"emitDeclarationOnly": true,
"esModuleInterop": true
}
}
(Note that allowJs
has to be removed because it is incompatible with declaration
. If you needed allowJs
, please explain your scenario and I'll try to help you solve it.) And compile the module with this command:
rm -rf dist && tsc && babel ./src --out-dir dist -x .js,.ts -D --verbose
You'll also have to change the export at the end of module/src/main.ts
to:
export default MOD;
because the TypeScript compiler does not recognize assignments to module.exports
in a .ts
file and Babel does not support export = MOD
. This should work as long as all consumers of the module use a default import. (Again, if you need to support consumers that do a plain require
, please explain your scenario and I'll see what I can do.)
Update
If you need an export assignment, since your .ts
file will need to say export = MOD
and Babel doesn't accept that, the only solution I can find is to run Babel on the JavaScript generated by tsc
in which the export = MOD
will have been translated to module.exports = MOD
. In an example configuration, module/tsconfig.json
is:
{
"compilerOptions": {
"target": "ES6",
"module": "commonjs",
"rootDir": "src",
"outDir": "ts-out",
"declarationDir": "dist",
"declaration": true,
"esModuleInterop": true
}
}
and the build command is:
rm -rf dist ts-out && tsc && babel ./ts-out --out-dir dist -x .js,.ts -D --verbose
(This is assuming you have some reason to use Babel at all rather than using the JavaScript output of tsc
directly.)
Since the project is importing module/dist/main
, and only a .js
file exists at that path, the only type information the TypeScript compiler has for that import is what it can extract from main.js
, which in general is going to be incomplete. What you should probably do is have tsc
on the module generate .d.ts
files alongside the .js
files. Then tsc
on the project will use the .d.ts
files. E.g., change module/tsconfig.json
to the following:
{
"compilerOptions": {
"target": "ES5",
"module": "commonjs",
"rootDir": "src",
"outDir": "dist",
"declaration": true,
"emitDeclarationOnly": true,
"esModuleInterop": true
}
}
(Note that allowJs
has to be removed because it is incompatible with declaration
. If you needed allowJs
, please explain your scenario and I'll try to help you solve it.) And compile the module with this command:
rm -rf dist && tsc && babel ./src --out-dir dist -x .js,.ts -D --verbose
You'll also have to change the export at the end of module/src/main.ts
to:
export default MOD;
because the TypeScript compiler does not recognize assignments to module.exports
in a .ts
file and Babel does not support export = MOD
. This should work as long as all consumers of the module use a default import. (Again, if you need to support consumers that do a plain require
, please explain your scenario and I'll see what I can do.)
Update
If you need an export assignment, since your .ts
file will need to say export = MOD
and Babel doesn't accept that, the only solution I can find is to run Babel on the JavaScript generated by tsc
in which the export = MOD
will have been translated to module.exports = MOD
. In an example configuration, module/tsconfig.json
is:
{
"compilerOptions": {
"target": "ES6",
"module": "commonjs",
"rootDir": "src",
"outDir": "ts-out",
"declarationDir": "dist",
"declaration": true,
"esModuleInterop": true
}
}
and the build command is:
rm -rf dist ts-out && tsc && babel ./ts-out --out-dir dist -x .js,.ts -D --verbose
(This is assuming you have some reason to use Babel at all rather than using the JavaScript output of tsc
directly.)
edited Nov 11 at 4:42
answered Nov 11 at 3:46
Matt McCutchen
13k719
13k719
Yes, your solution works indeed. But as you said it no longer works withrequire
, which is something that I want. I want anyone to be able to use my module, whether it's with CommonJS or ES Modules.When I download a package on NPM, I can usually use both systems. Take one example, Express, they use module.exports, which is why I tried this way. I'm surprised that it doesn't work with my module. I don't really understand the difference.
– h-Reser
Nov 11 at 4:23
See the updated answer for how to makerequire
work.
– Matt McCutchen
Nov 11 at 4:43
I managed to do it. I think I was lacking some comprehension of the CommonJS and ES modules. Thanks a lot for looking into that, you were a big help :)
– h-Reser
Nov 11 at 20:08
add a comment |
Yes, your solution works indeed. But as you said it no longer works withrequire
, which is something that I want. I want anyone to be able to use my module, whether it's with CommonJS or ES Modules.When I download a package on NPM, I can usually use both systems. Take one example, Express, they use module.exports, which is why I tried this way. I'm surprised that it doesn't work with my module. I don't really understand the difference.
– h-Reser
Nov 11 at 4:23
See the updated answer for how to makerequire
work.
– Matt McCutchen
Nov 11 at 4:43
I managed to do it. I think I was lacking some comprehension of the CommonJS and ES modules. Thanks a lot for looking into that, you were a big help :)
– h-Reser
Nov 11 at 20:08
Yes, your solution works indeed. But as you said it no longer works with
require
, which is something that I want. I want anyone to be able to use my module, whether it's with CommonJS or ES Modules.When I download a package on NPM, I can usually use both systems. Take one example, Express, they use module.exports, which is why I tried this way. I'm surprised that it doesn't work with my module. I don't really understand the difference.– h-Reser
Nov 11 at 4:23
Yes, your solution works indeed. But as you said it no longer works with
require
, which is something that I want. I want anyone to be able to use my module, whether it's with CommonJS or ES Modules.When I download a package on NPM, I can usually use both systems. Take one example, Express, they use module.exports, which is why I tried this way. I'm surprised that it doesn't work with my module. I don't really understand the difference.– h-Reser
Nov 11 at 4:23
See the updated answer for how to make
require
work.– Matt McCutchen
Nov 11 at 4:43
See the updated answer for how to make
require
work.– Matt McCutchen
Nov 11 at 4:43
I managed to do it. I think I was lacking some comprehension of the CommonJS and ES modules. Thanks a lot for looking into that, you were a big help :)
– h-Reser
Nov 11 at 20:08
I managed to do it. I think I was lacking some comprehension of the CommonJS and ES modules. Thanks a lot for looking into that, you were a big help :)
– h-Reser
Nov 11 at 20:08
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53245289%2fclass-property-doesnt-exist%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown