Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide default export for ES6 / TypeScript users #97

Closed
felixfbecker opened this issue Jul 12, 2016 · 6 comments
Closed

Provide default export for ES6 / TypeScript users #97

felixfbecker opened this issue Jul 12, 2016 · 6 comments

Comments

@felixfbecker
Copy link

Currently, BigNumber only uses module.export to export itself. For users of ES6 and TypeScript it would be nice to have BigNumber also as a named export or default export, e.g. if you could do

module.exports = constructorFactory();
module.exports.BigNumber = module.exports;
module.exports.default = module.exports;

which would allow to do

import {BigNumber} from 'bignumber';

I'm currently writing TypeScript definitions for BigNumber and this would simplify things a lot, as I could export other interfaces besides the main BigNumber class.

@MikeMcl
Copy link
Owner

MikeMcl commented Jul 12, 2016

This seems reasonable, but please can you further explain why you want to be able to use

import {BigNumber} from 'bignumber';

rather than

import BigNumber from 'bignumber';

I don't yet know enough about TypeScript to understand why it "would simplify things a lot", or how it would enable you to "export other interfaces besides the main BigNumber class".

@felixfbecker
Copy link
Author

@MikeMcl that is just a matter of style. You export the BigNumber class, the BigNumberError class (for proper instanceof checks) and the TypeScript definitions can also export some interfaces. Then in addition, you say BigNumber should be the default export.

import {BigNumber, BigNumberError, Configuration} from 'bignumber.js';
// easier than import {default as BigNumber, BigNumberError} from 'bignumber.js';

try {
  const x = new BigNumber(123);
} catch (e) {
  if (e instanceof BigNumberError) {
    // TypeScript now knows that e has all the properties of BigNumberError
  }
}

the definitions would look like this:

declare module 'bignumber.js' {
  export interface Configuration {
    DECIMAL_PLACES: number;
  }
  export class BigNumber {
    static config(config: Configuration): Configuration;
  }
  export class BigNumberError extends Error {}
  export default BigNumber;
}

For the legacy module.exports TypeScript has a special syntax, export =. But when you use it you can only export one item:

declare module 'bignumber.js' {
  // cannot export this :(
  interface Configuration {
    DECIMAL_PLACES: number;
  }
  export class BigNumber {
    static config(config: Configuration): Configuration;
  }
  export = BigNumber;
}

and you have to use require() instead of import, which prevents you from compiling to ES6.

import BigNumber = require('bignumber.js');

TypeScript definitions don't only help TypeScript users, but power editor autocompletion in editors for JavaScript users. It would also benefit Node users as import/export may already land in Node 7 and all users who write front-end code in ES6.

@felixfbecker
Copy link
Author

If you are interested, check out https://github.com/felixfbecker/typed-bignumber.js

@MikeMcl
Copy link
Owner

MikeMcl commented Jul 14, 2016

I've played around with it and yes it seems to work, but its hacky and irritating to have to add two redundant properties (which will show up in intellisense) to the BigNumber class so that ES6 imports work.

Is this something other libraries have done? Will it work okay with Babel?

I also note that TypeScript compiles every constructor call to, e.g. new bignumber_1.BigNumber(1.23); or new bignumber_1.default(1.23); depending on the form of the import, which isn't great.

@felixfbecker
Copy link
Author

Yes, sequelize for example. I also saw it in other libraries.

It also has the added benefit that you could export the BigNumberError class (and possibly more in the future) aswell, all while maintaining BC. In the end, module.exports was never a standard, it was an extension by NodeJS. Both CommonJS and ES6 use named and default exports.

Typings work as they are, but what would maybe make it feel a bit "hacky" for ES5 users (honestly I think most wont even notice) would make it way less "hacky" for ES6 and TS users.

@MikeMcl
Copy link
Owner

MikeMcl commented Jul 14, 2016

Okay, I just pushed v2.4.0.

Let me know if there any issues.

Great work on the definitions by the way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants