Web3.js: TypeScript type definitions don't work in NodeJS

Created on 11 Mar 2019  路  7Comments  路  Source: ChainSafe/web3.js

Description

The TypeScript type definitions do not work when used as a dependency in NodeJS. In the *.cjs.js files used by NodeJS, the old commonjs exports = form is used to export the modules, whereas in the TypeScript bindings the exports are defined to use the ES6 export default form, mapping to exports.default = in the *.esm.js files.

This issue is closely related to #1248.

Error Logs

const web3 = new web3_1.default(null);
             ^

TypeError: web3_1.default is not a constructor

Versions

  • web3.js: 1.0.0-beta.38
  • nodejs: 10.14.1
  • typescript: 3.3.3333
types

Most helpful comment

Hey @yaram so your issue is due to the mismatch between how commonjs export stuff module.exports = something and how ES6 export stuff export default something.

To fix this it you just have to enable esModuleInterop in your tsconfig compile option, also enable allowSyntheticDefaultImports for typesystem compatibility :

"compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    ....

This then will allow you to import as you would anywhere like:

import Web3 from "web3";

If you look at the compiled source now it does:

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const web3_1 = __importDefault(require("web3"));
const web3 = new web3_1.default("https://rinkeby.infura.io/");

The __importDefault is imported now and wraps web3 in it which fixes the issues with it compiling fine and it not running when you tried to.

Will add these instructions to the README so its clear how to get the typing's to work in a commonjs module.

Thanks
Will close now
Josh

All 7 comments

Have you tried import * as web3 from 'web3'?

That would work in plain old ES6, but because of the misastched TypeScript type definitions, the TypeScript compiler complains with a type error in the form of

index.ts:3:14 - error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.

3 const web3 = new Web3(null);
               ~~~~~~~~~~~~~~

One solution would be to have the TypeScript type definitions export both in the ES6 style and in the commonjs style but as far as I can tell that's not possible.

Hey thanks for raising this, I will try to recreate your issue tomorrow and take a look. You are just trying to use the types in a standard node app? can you paste how your trying to import it please? that would be awesome.

I think I know what it is - please still supply the above so I can confirm (I only really need the import your trying to do). I can then reply tomorrow once I鈥檓 online as I鈥檓 UK time and it鈥檚 1am here at the moment. Thanks 馃憤

I've uploaded a test package here. Originally I was trying to use web3@^1.0.0-beta.38 from TypeScript in tests.

Hey @yaram so your issue is due to the mismatch between how commonjs export stuff module.exports = something and how ES6 export stuff export default something.

To fix this it you just have to enable esModuleInterop in your tsconfig compile option, also enable allowSyntheticDefaultImports for typesystem compatibility :

"compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    ....

This then will allow you to import as you would anywhere like:

import Web3 from "web3";

If you look at the compiled source now it does:

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const web3_1 = __importDefault(require("web3"));
const web3 = new web3_1.default("https://rinkeby.infura.io/");

The __importDefault is imported now and wraps web3 in it which fixes the issues with it compiling fine and it not running when you tried to.

Will add these instructions to the README so its clear how to get the typing's to work in a commonjs module.

Thanks
Will close now
Josh

Was this page helpful?
0 / 5 - 0 ratings