You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'd like to see official documentation of the design decision TS has made regarding type checking of operators now that bigint
is in play.
Use Cases
The closure-compiler team is currently working on our support for BigInt.
We want to make sure the type design choices we make there are compatible with TS going forward.
It appears that right now when you perform an arithmetic operation on 2 any values, TS infers the result to be of type number, even in ESNext mode where one might expect the result to be number|bigint.
I am inclined to do the same for closure-compiler, but I'd first like to make sure that this behavior was an intentional design choice for TS and not an oversight/bug that is likely to change in the near future.
My point of view on this is that logically the * operator (for example) is overloaded, so there are really 2 versions of it.
The original * can take anything (except bigint), and always returns a number.
The new bigint * bigint version, which always returns a bigint, or throws an exception if one operand is not a bigint.
The compiler should assume it's dealing with #1, unless type information indicates it is seeing #2.
Insisting that all operands be clearly typed as bigint if you want bigint results prevents users from
crossing the streams and accidentally mixing bigint and number values in computations.
Examples
What is the result type of bigint|number * bigint|number? I expect bigint|number with no error message, since you may want to write methods that are intentionally meant to work for either case.
What is the result type of bigint * any? I expect the bottom/can't happen type, and an error message since we can't be sure that the right operand will be a bigint at runtime.
What is the result type of any * any? I expect number (current TS behavior), because it's undesirable for old code to suddenly think it might have a bigint, and new code should be explicit about using bigint to avoid runtime errors.
Checklist
My suggestion meets these guidelines:
[ X ] This wouldn't be a breaking change in existing TypeScript/JavaScript code
[ X ] This wouldn't change the runtime behavior of existing JavaScript code
[ X ] This could be implemented without emitting different JS based on the types of the expressions
[ X ] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
As we discussed, while the change itself is trivial (#39029), my thinking is that the potential breaks of changing this make it not worth it for the purposes of correctness. Maybe it is too trivial, but it would be strange for the following to stop working:
functionfoo(a,b){returna*b*Math.random();// uh oh! can't do '(bigint | number) * number'!}
We also don't have feedback that users are unhappy with the current behavior which has been around since TypeScript 3.2 (which had a full release at the end of November 2018), though admittedly that is still fairly new and our support never provided polyfills.
Finally, something I think you and I both have a hunch about, was that a bunch of of code that is being migrated to typed JavaScript that multiplies anys were written with the presumption of only numbers - not bigints - being used for multiplication. Given that any is already unsound, and that numbers are dramatically more prevalent (and will likely be onwards), I think sticking with number is reasonable.
Search Terms
bigint operator type checking
Suggestion
I'd like to see official documentation of the design decision TS has made regarding type checking of operators now that bigint
is in play.
Use Cases
The closure-compiler team is currently working on our support for BigInt.
We want to make sure the type design choices we make there are compatible with TS going forward.
It appears that right now when you perform an arithmetic operation on 2
any
values, TS infers the result to be of typenumber
, even in ESNext mode where one might expect the result to benumber|bigint
.https://www.typescriptlang.org/play/?target=99#code/DYUwLgBAhgXNB2BPCBeCBGeBuAUKSARnFEqhtnuBAMZwECWA5vfJGlBAFQQFZA
I am inclined to do the same for closure-compiler, but I'd first like to make sure that this behavior was an intentional design choice for TS and not an oversight/bug that is likely to change in the near future.
My point of view on this is that logically the
*
operator (for example) is overloaded, so there are really 2 versions of it.*
can take anything (exceptbigint
), and always returns anumber
.bigint * bigint
version, which always returns abigint
, or throws an exception if one operand is not abigint
.The compiler should assume it's dealing with #1, unless type information indicates it is seeing #2.
Insisting that all operands be clearly typed as
bigint
if you wantbigint
results prevents users fromcrossing the streams and accidentally mixing
bigint
andnumber
values in computations.Examples
bigint|number * bigint|number
? I expectbigint|number
with no error message, since you may want to write methods that are intentionally meant to work for either case.bigint * any
? I expect thebottom/can't happen
type, and an error message since we can't be sure that the right operand will be abigint
at runtime.any * any
? I expectnumber
(current TS behavior), because it's undesirable for old code to suddenly think it might have abigint
, and new code should be explicit about usingbigint
to avoid runtime errors.Checklist
My suggestion meets these guidelines:
The text was updated successfully, but these errors were encountered: