-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
No warning when using unary +/- operators on functions and objects? #20131
Comments
It may not make much sense for anyone to ever use Because JavaScript tries to make sense of a lot of operations that would cause other languages to throw an error, you could argue that TypeScript should prevent (or warn) you for many valid operations. For example, adding a string to a number? |
Relevant reading about "not incorrect code" by @RyanCavanaugh:
I think the litmus test isn't usually "is this code invalid JavaScript" but "is this code likely to be a bug" (and whether the false positives you would get by flagging it as an error are preferable to the false negatives you would get by allowing it). JavaScript allows almost everything. TypeScript should warn you when you are doing something allowable-but-probably-wrong. This issue is asking whether people really use unary |
Seems wrong when we can be reasonably confident that the result will be |
As @calebsander points out, the single element tuple when it's value is Also, any object that overrides var x = +({valueOf() { return '33'; }}) // 33 or var x = +({toString() { return Math.random() > 0.5 ? '3' : 'abc'; } }); // sometimes 3 sometimes NaN |
If we intentionally disallow the single-element tuple and objects with var w = +({valueOf: ()=>''}); // 0
var x = +([{toString: ()=>'1'}]); // 1
var y = -([[[[[[[-2]]]]]]]); // 2
var z = +([{valueOf() { return 3; }}]); // 3 so I could either rewrite them or assert the quantity in parentheses as var w = +({valueOf: ()=>''} as any); // 0
var x = +([{toString: ()=>'1'}] as any); // 1
var y = -([[[[[[[-2]]]]]]] as any); // 2
var z = NaN; // not 3 Hey, did you realize that |
I'm really skeptical that anyone uses |
We agreed that the current behavior is dumb, but would prefer to group this change into an overall revamp of how the general numeric operators (especially |
I just came across this recently. I declared some strings across multiple lines, concatenated with +, and in one place accidentally put a + at the end of one line and the start of the next. I was very surprised that it got through type checking. My feeling is that the unary +/- operators are a special case. I think semantically they really shouldn't be operators at all, but rather part of a numeric literal. I suspect they were only made into operators in the first place to make parsing easier. |
Parsing unary operators as operators is actually harder than treating them as part of the literal. However, if they weren't operators you wouldn't have been able to write |
How about supporting a declaration that a type supports the unary operator, then if someone designs a type meant to be used like that, it can be. Same could be said for binary operators I guess. Unary could be associated with the type directly: type HasUnaryPlus = { +: number; };
const x: HasUnaryPlus = aquireTheThing();
console.log(+x); // OK Binary operators would need to be declared separate from the types: type A = ... ;
declare operator+ (a0: A, a2: A): A; Could be useful for e.g. moment: moment(moment() + moment.duration(3, 'days')); The code makes sense, and runs fine as javascript, but does not validate as typescript. |
Could you make It seems there is already a concept in TypeScript of what is "numeric," and I don't think any of the concerns about idiomatic uses of unary I just ran into a bug in my program where I wrote |
Should unary operators even be allowed in TS? |
I find it hilarious (in a morbid sort of way) that implicitly converting a function to a string to a number is perfectly fine, but I can't even use an object with a const wtf = -(() => "func") // you do you, javascript developer!
const stringableFn = () => {};
stringableFn.toString = () => "I'm a key!";
const slowDownThereBuddy = {
[stringableFn]: 1 // A computed property name must be of type 'string', 'number', 'symbol', or 'any'.ts(2464)
} This annoys the hell out of me since this is a common pattern with many redux action creators libraries. I have a hard time believing that the former example is considered most likely intentional, and the latter is considered most likely a mistake. |
I just want to point out that let fraction = math.fraction(2, 3)
let approxResult = +fraction Globally disallowing the unary plus for objects sounds like a very bad idea here. |
Is there lack of appetite to altering this behavior? Just wondering - I got redirected here from eslint github page: typescript-eslint/typescript-eslint#3200 If it's not coming soon in TS, I'm wondering if it's a good idea to implement an eslint rule for this? |
TypeScript Version: 2.6.1
Code
Expected behavior:
Unary
+
or-
is only applicable to anumber
or maybe astring
. I would expect the lines listed as// no error
to be errors.Actual behavior:
Unary
+
and-
never generates a warning no matter what crazy stuff I try to apply it to.I was made aware of this behavior by a recent Stack Overflow question. I see from #7019 that unary
+
and-
onstring
s is supported, and I guess I can understand that as a way to parse astring
into anumber
(for+
, anyway. Is-
really used like this in practice?). But functions? objects? Seems more likely to be an error than intentional to me. Thoughts?The text was updated successfully, but these errors were encountered: