Typescript: Support bigint for ES2020

Created on 8 Oct 2019  路  14Comments  路  Source: microsoft/TypeScript


TypeScript Version: master branch


Search Terms: bigint es2020 2020

Code

100n
// Error: BigInt literals are not available when targeting lower than ESNext.

Expected behavior: ES2020 should support bigints, because it's now in Stage 4 and is just merged into the spec 馃帀

Actual behavior: It does not.

Playground Link: https://www.typescriptlang.org/play/?target=7&ssl=1&ssc=5&pln=1&pc=1#code/IwBhDsg

Related Issues:

ES Next Moderate Suggestion help wanted

Most helpful comment

This problem just became much bigger with TypeScript 3.7's release. bigint is now supported in all major browsers and NodeJS but optional chaining is not. If I set the TypeScript compiler target to es2020, then I get an error saying that I cannot use bigints. If I set the compiler target to esnext, then optional chaining will not be transpiled and my code will not run anywhere.

This means a project right now cannot use both bigint and optional chaining since TypeScript compiler doesn't allow granular transpilation. The simple fix for this specific problem is to resolve this issue. The bigger/much more involved fix is to make it so the compiler supports fine grained transpilation.

What needs to happen to get this issue resolved? I think that this should be upgraded to a bug due to the introduction of optional chaining in TS 3.7, and we shouldn't wait for 3.8.0 for this to go out.

All 14 comments

Any notice or decision made about this or #33874? I think this should be part of TS 3.7.

For instance, in our team we are using Node.js 12 (12.12.0 at the moment) that supports BigInt literals just fine, but we need to set target to ESNext in order to use them, which is a big problem since targeting ESNext doesn't transform optional chaining and nullish coalescing operators that are passed _as-is_, although they're not supported in Node.js 12.

I mean this code:

const obj = { x: 1 };
const y = obj?.x;
const b = 123n;

is transpiled to this when targeting ESNext:

const obj = { x: 1 };
const y = obj?.x;
const b = 123n;

but Node.js doesn't support ?. operator yet and fails. When targeting ES2020 the same code produces:

var _a;
const obj = { x: 1 };
const y = (_a = obj) === null || _a === void 0 ? void 0 : _a.x;
const b = 123n;

which runs OK but TS fails with the message "BigInt literals are not available...".

3.7 is already feature-complete, and will be released in approximately 3 weeks, so this is 3.8-bound. Hopefully I can also get optional chaining to be in ES2020 too!

This problem just became much bigger with TypeScript 3.7's release. bigint is now supported in all major browsers and NodeJS but optional chaining is not. If I set the TypeScript compiler target to es2020, then I get an error saying that I cannot use bigints. If I set the compiler target to esnext, then optional chaining will not be transpiled and my code will not run anywhere.

This means a project right now cannot use both bigint and optional chaining since TypeScript compiler doesn't allow granular transpilation. The simple fix for this specific problem is to resolve this issue. The bigger/much more involved fix is to make it so the compiler supports fine grained transpilation.

What needs to happen to get this issue resolved? I think that this should be upgraded to a bug due to the introduction of optional chaining in TS 3.7, and we shouldn't wait for 3.8.0 for this to go out.

Same problem with trying to use null coalescing operator. It isn't supported anywhere, which means I cannot currently use it in a project with bigint because bigint isn't part of es2020 yet (according to TS).

Even if we add bigint for es2020, I plan to request the advancement of optional chaining and nullish coalescing in December, so that should also land in es2020. That means that by the time 3.8 goes out, you'll be left with the same situation, but engines will have implemented both. So waiting for engines to ship the features is probably your best bet.

The next node LTS may have optional chaining/nullish coaelescing (Oct 2020). But if 3.8 isn't going to differentiate between these features, we can't use BigInt literals for at least another year in production - even though it's been broadly available since 2018. I vote for resolving this issue as-is.

I found that I can use https://www.npmjs.com/package/big-integer instead bigint literals because internally they will be converted to bigints on Node 12.

I can write now ie.

import bigInt from "big-integer"
function delta(start: bigint, end: bigint): number {
  return bigInt(end)
      .minus(start)
      .divide(1000000)
      .valueOf()
}

instead

function delta(start: bigint, end: bigint): number {
  return Number((end - start) / 1_000_000n)
}

and it is small price for optional chaining and nullish coaelescing even if bigint is supported in Node since 2018.

There are a number of libraries for dealing with large numbers in JavaScript, including bn.js bignumber.js, big-integer, jsbn, big-number, big-number, decimal.js. This thread is about making it so we can actually use native bigint and optional chaining in the same project before October 2020. If you are satisfied with the ergonomics and the interoperability problems of using a library don't cause undue hardship then using a library is definitely an option.

@MicahZoltu I absolutely agree: this is real shame that I can't use all features in the same NodeJS project because of Typescript limitation and now I have wait 2 years after bigint was provided natively. Syntax in 3rd party libraries usually is ugly and it looks like quick-and-dirty solution. I have strong feeling that NodeJS is not a first class citizen for Typescript project.

@dex4er The same problem exists for browser targets. All major browsers support native bigint, but no major browser supports optional chaining. It is unknown when any browsers will add optional chaining support, but until all of the major ones do we cannot use ES that outputs optional chaining.

@MicahZoltu Ah, we don't need to use external libraries. All I need is to use explicit BigIntConstructor that is supported in es2020 target:

function delta(start: bigint, end: bigint): number {
  return Number((end - start) / BigInt(1000000))
}

works as expected and it is not so ugly. All we miss are bigint literals. The type itself is supported. If you need literals badly then probably it would be possible to use custom WebPack plugin.

@dex4er BigInt(10**50) will result in a rounded value, not an exact value. BigInt("100000000000000000000000000000000000000000000000000") will work I think... but ugh...

@MicahZoltu BigInt("1" + "0".repeat(50))

Thanks @saschanaz!

Was this page helpful?
0 / 5 - 0 ratings