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

Support for TC39 "BigInt: Arbitrary precision integers in JavaScript" proposal #15096

Closed
tarcieri opened this issue Apr 10, 2017 · 35 comments
Closed
Assignees
Labels
Committed The team has roadmapped this issue ES Next New featurers for ECMAScript (a.k.a. ESNext) Suggestion An idea for TypeScript

Comments

@tarcieri
Copy link

tarcieri commented Apr 10, 2017

The ECMAScript Technical Committee 39 has put forward a concrete proposal for adding integers to JavaScript:

https://tc39.github.io/proposal-bigint/

The proposal adds a new syntax for integer literals:

42n // This is an integer literal

Implicit conversions to/from numbers and integers and expressions with mixed operands are expressly disallowed:

42n + 1 // Throws TypeError

Type constructors are provided that wrap at specified widths:

  • Integer.asUintN(width, Integer): Wrap an Integer between 0 and 2**width-1
  • Integer.asIntN(width, Integer): Wrap an Integer between -2**(width-1) and 2**(width-1)-1
  • Integer.parseInt(string[, radix]): Analogous to Number.parseInt, to parse an Integer from a String in any base.

Though not stated in the spec, these constructors should theoretically hint to the VM when it's possible to use a native 64-bit integer type instead of a bignum, and could therefore possibly be used by TypeScript to implement int64 and uint64 types in addition to e.g. an integer type of arbitrary precision.

I know people have been asking for integers for quite some time (e.g. #195, #4639), but have been held back by lack of native support of an integer type in JavaScript itself. Now it seems this proposal is stage 2 (scratch that, stage 3!) and has multi-browser vendor backing, so perhaps the prerequisites are finally in place to make integers happen.

@DanielRosenwasser DanielRosenwasser added ES Next New featurers for ECMAScript (a.k.a. ESNext) Suggestion An idea for TypeScript labels Apr 10, 2017
@aluanhaddad
Copy link
Contributor

🚲:house:
Why didn't they choose Z for the literal suffix?

@tarcieri tarcieri changed the title Support for TC39 "Integer: Arbitrary precision integers in JavaScript" proposal Jun 2, 2017
@tarcieri
Copy link
Author

Looks like this may be landing in Babel soon:

babel/proposals#2

@tarcieri
Copy link
Author

Initial (WIP) babel PR for this: babel/babel#6015

@Cixelyn
Copy link

Cixelyn commented Aug 1, 2017

Looks like the BigInt proposal has also hit stage 3 (tc39/proposal-bigint@1b4c7e6). Would be awesome to see TypeScript support.

@raix
Copy link

raix commented Jan 15, 2018

Personally looking forward to getting the feature available - only concern is the ducktape syntax, my hope is that typescript can help keep the syntax clean.

@styfle
Copy link
Contributor

styfle commented Mar 7, 2018

@RyanCavanaugh @mhegazy @andy-ms
Are there plans to started implementing BigInt now that it's Stage 3?

Or does it need to land in Edge first?

@Bnaya
Copy link

Bnaya commented Mar 7, 2018

BigInt is implemented in V8, means we will have it in chrome and V8 soon
refs:
https://twitter.com/bmeurer/status/969656997879713792

@samrg472
Copy link

samrg472 commented Jun 7, 2018

Node 10.4.0 ships with V8 6.7, a flag is no longer needed to be able to use big integers.

@Kingwl
Copy link
Contributor

Kingwl commented Jun 8, 2018

seems have a plan to support it on 3.0

@styfle
Copy link
Contributor

styfle commented Jun 8, 2018

@Kingwl Yes, I see it on the roadmap for 3.0 as you said 👍

For others viewing this issue, the roadmap can be found on the wiki here: https://github.com/Microsoft/TypeScript/wiki/Roadmap#30-july-2018

@tarcieri
Copy link
Author

tarcieri commented Jun 8, 2018

Fantastic!

Looks like support just landed in Babel too: babel/babel#8006

@FranklinYu
Copy link

@tarcieri That does not do the transformation right? So 123n will be simply be kept the same in output?

@Kingwl
Copy link
Contributor

Kingwl commented Jun 10, 2018

i'm not sure that will we add the transformer (maybe polyfill) as @FranklinYu said
if we do not process that, i'm Interesting for the scanner or parser

@NN---
Copy link

NN--- commented Jun 14, 2018

Does it mean that keyof type will be changed again to include bigint?

@calebsander
Copy link
Contributor

calebsander commented Jun 26, 2018

While TypeScript 3.1 is still in the works, here is a placeholder. Put this in a .d.ts file (e.g. bigint.d.ts) that is included in your compilation:

type BigInt = number
declare const BigInt: typeof Number

This allows you to use BigInt as a type annotation and lets you call the BigInt function. Since BigInt values are meant to work with all the same arithmetic operations as Number, type-aliasing BigInt to Number should allow you to use it before TypeScript includes it in the standard library. BigInt literals still won't be able to be parsed, though, so you will have to use the BigInt constructor. For example, 1n + 2n can be written BigInt(1) + BigInt(2). For literal integers that exceed the 53-bit Number limit, you can pass them as strings instead: BigInt('9223372036854775807'). Hope this is helpful!

@HolgerJeromin
Copy link
Contributor

@calebsander but
12n+3.14
would be valid with your code but is not in the browsers.

@calebsander
Copy link
Contributor

TypeScript does not generally provide polyfills to add support for features to old platforms. The compiler performs simple syntactic desugaring, e.g. to implement import-export and async-await, but supporting bigint computations would require a full-blown library to represent bigint values and implement their operations. bigint literals (e.g. 123n) also cannot be polyfilled since they will cause syntax errors on runtimes which don't support them. I would suggest using one of the existing big integer libraries for JS, e.g. big-integer. If you want to also use native bigint if it is supported, you could write a simple wrapper which chooses to represent big integers either natively or with one of these libraries, depending on whether native support exists.

@tarcieri
Copy link
Author

There's work underway to support it in babel if you need support on older platforms: babel/proposals#2

@FranklinYu
Copy link

I thought it may be feasible for TypeScript compiler to recognize and transpile 9007199254740991n into BigInt("9007199254740991") and defer the actual implementation of BigInt to other libraries (so we avoid Babel), but then I realized that the proposal does not provide any methods like i1.add(i2) or add(i1, i2), and libraries won't provide operator overloading (not possible in JS). It feels bad to introduce Babel only for this, since TypeScript compiler is already able to compile to old JavaScript.

@calebsander
Copy link
Contributor

calebsander commented Sep 8, 2018

I implemented BigInt support in #25886, which is still out for review. I've been using bigint in a number of TypeScript projects recently by substituting my fork for the npm package. Here is how you can use it in your own projects:

1. Add the dependency "typescript": "calebsander/TypeScript#feature/bigint-lkg" in your package.json
2. If you need to use BigInt library definitions (e.g. for BigInt or BigInt64Array), modify your tsconfig.json to either set target to "esnext" or add "esnext.bigint" to the lib option
3. If you need to use BigInt literals (e.g. 0xABCDn), add "experimentalBigInt": true to your tsconfig.json

(Obviously, it would be great if the PR could be merged into TypeScript, but hopefully this is helpful as a temporary solution.)

PR #25886 was merged! Use "typescript": "next" instead of my repository.

@no2chem
Copy link

no2chem commented Sep 12, 2018

@calebsander - thanks! I'm using your PR successfully in https://github.com/no2chem/bigint-buffer, but it seems that a lot of tooling (webpack, typedoc) will remain broken, so the workaround you suggested in #15096 (comment) helps a lot in these cases (for example, I include bigint.d.ts when using typedoc to build documentation).

@RyanCavanaugh RyanCavanaugh added the Committed The team has roadmapped this issue label Sep 17, 2018
@gatsbyz
Copy link

gatsbyz commented Sep 20, 2018

Thanks for this!

@NN---
Copy link

NN--- commented Nov 14, 2018

What about indexer type ?
This code is valid JS:

[1,2,3][1n]

It means that indexer type now has to be allowed as: string | number | bigint

@novemberborn
Copy link

[1,2,3][{toString(){return '1'}}] also works. I'm not sure how indexing is specified in the language though, and whether that includes BigInt. If it doesn't, I'm not sure whether BigInt should be allowed.

@NN---
Copy link

NN--- commented Nov 14, 2018

@novemberborn You have a more general suggestion.
Currently Array is defined as type accepting only number as index.
Your suggest to extend indexer type beyond number | string | bingint.

type Indexer = number | string | bigint | ({ toString(): string|number }) 
@novemberborn
Copy link

Sorry, I was suggesting that there are other types that work in JavaScript, but for sensible reasons are not supported in TypeScript.

@NN---
Copy link

NN--- commented Nov 14, 2018

BigInt is allowed to be index in ES, so there is no question here.
Btw, I think there was no issue about type with toString property as indexer.

@calebsander
Copy link
Contributor

What about indexer type ?
This code is valid JS:

[1,2,3][1n]

It means that indexer type now has to be allowed as: string | number | bigint

We considered this in #25886 and decided against adding bigint as an index type. See my comment: #25886 (comment). As @novemberborn says, any value can be used as a key in JS because any value can be converted to a string. Really, string and symbol are the only true index types. number is included because Arrays and TypedArrays are meant to be indexed with numeric indices. Since number can store a 53-bit unsigned integer, it is sufficient to index anything stored in almost all modern address spaces (e.g. the 48-bit x86-64 address space). There is really no reason to use a bigint as a numeric index unless you have a sparse array (in which case an object should be used instead). You can always just convert the bigint to a number or string, which would be a valid index type.

@NN---
Copy link

NN--- commented Nov 15, 2018

Thanks.
Good point.

@schmidsi
Copy link

It is probably a bit off-topic but I searched some time for a possibility to use BigInt today and came across this project: https://github.com/GoogleChromeLabs/jsbi

It has the same API and there is a babel-transform plugin to remove it eventually.

@calebsander
Copy link
Contributor

Integrating JSBI was already discussed in #28756

@hixio-mh
Copy link

hixio-mh commented Sep 4, 2020

Merge pull requested

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Committed The team has roadmapped this issue ES Next New featurers for ECMAScript (a.k.a. ESNext) Suggestion An idea for TypeScript