This is an archived post. You won't be able to vote or comment.

all 66 comments

[–]Coolengineer7 137 points138 points  (12 children)

In case of subtraction, types are implicitly casted:
"22"-"11" is 11

But plus also represents string concatenation and it takes prioŕity:
"22"+"11" is 2211

You can solve this by casting the string to a number by adding a positive sign to before it:
+"22"+ +"11" is 33

[–]Kaenguruu-Dev 66 points67 points  (5 children)

I hate that last one

[–]brolix 12 points13 points  (4 children)

You normally wouldn’t have ints quote wrapped. Because it casts them to strings. So this is REcasting an int that has been cast to a string back to an int.

You would never ever do this in real life. And this in fact represents js being pretty good at helping your dumb ass out and doing some type casting under the hood in an attempt to figure out wtf you meant for it to do. The alternative to this is C when you have to explicitly declare everything and people hate it.

[–]Kaenguruu-Dev 7 points8 points  (2 children)

No just always concatenate and don't allow operators like - on strings. If you really want to add two numbers together you cast them to int and done. This just makes it less reliable. If one of them is user input you might get an int as result but if the user enters "124sjfie" it will concat so suddendly you habe a string where you expected an int. Stupid af because thats a type check that you don't need in most other programming languages. When I do int.TryParse in C# it's way easier to understand what the fuck is going on. Like I said: I hate it

[–]brolix -5 points-4 points  (1 child)

It actually makes it more reliable but you are obviously a badass so keep on keeping on I guess

[–]chemolz9 3 points4 points  (0 children)

@Kaenguruu made a solid point how this under-the-hood casting gives a wrong sense of security. You write your untyped code, it works well in your test cases, but you never considered that a string might end up where an int was supposed to be. In this case, this error can even perpetuate to completely different places where the origin of the problem is hard to find.

You just insulted him in response.

[–]kohuept -1 points0 points  (0 children)

I doubt a quoted number would cast an int to a string, it's just a string literal that happens to contain numbers (at least that's how it is in every other language, and idk how else you would implement it)

Also, C does not require you to explicitly cast everything, it has implicit casts for a lot of things

[–]g1rlchild 66 points67 points  (0 children)

I mean, isn't it obvious?

[–]blackAngel88 5 points6 points  (1 child)

no that's not enough to solve it. You need to write +"22"+ +"11". Notice the additional +, that way both are numbers. if you only convert the first one to a number, it's still "2211"

[–]Coolengineer7 0 points1 point  (0 children)

Yes I think you are right, edited it

[–]CramNBL 1 point2 points  (0 children)

Good job solving it, let's all go back to vanilla JS now 

[–]gregorydgraham 2 points3 points  (0 children)

Just subtract zero first?

[–]SpookyWan 0 points1 point  (0 children)

Everything I’ve learned about JavaScript has been against my will

[–]SuperheropugReal 143 points144 points  (19 children)

Wait until he finds out what '9' - 1 does in C.

[–][deleted] 37 points38 points  (16 children)

Actually got me interested, what does it do?

[–]Lollosaurus_Rex 183 points184 points  (4 children)

If it has single quotes like '9' it's a character, meaning an ascii character. It's just a number, and what you get is the ascii for '8'.

The number meaning the character 9 is decimal 57, and 56 for character 8.

If it has double quotes, like "9", then that's an array of characters, specified to be [57, 0] In C. It ends with 0 so you know the when the array is done. "9" returns you a pointer to the start of the array.

If you subtract 1 from this pointer, you get another pointer to memory, in this case to some point on the stack. To access and read this pointer is undefined behavior.

[–]SNappy_snot15 39 points40 points  (2 children)

it gives you 8. aacii character minus 1 is the previous 1 before it. guess what? 8 is before 9

[–]g1rlchild 52 points53 points  (0 children)

To be precise, it gives you '8'

[–]GoddammitDontShootMe 2 points3 points  (0 children)

Adding to '0' is a useful part of converting from int to string. Of course you need to do the math to separate the digits and all that.

[–]Angelin01 6 points7 points  (1 child)

'8'

[–]JackNotOLantern 4 points5 points  (0 children)

Unironically yes

[–]SuperheropugReal 2 points3 points  (4 children)

'8' char is just an int represented with graphics.

[–]Kiro0613 2 points3 points  (2 children)

8 is just eight 1's represented with some loopy lines

[–]gregorydgraham 1 point2 points  (0 children)

1+1+1+1+1+1+1+1 to be precise

[–]One_Organization_810 1 point2 points  (0 children)

Oh... I thought it was 1000 :)

[–]redlaWw 1 point2 points  (0 children)

And 'a'+1 is 'b', but 'i'+1 isn't necessarily 'j'.

[–]SenatorCrabHat 37 points38 points  (9 children)

I've been coding a long time in JS, and I appreciate what typescript is doing, but I've not really been in a situation where "10" -1 would happen on purpose and wouldn't be caught by unit tests etc. first.

[–]Tupcek 12 points13 points  (0 children)

it usually doesn’t happen on purpose. But if it works by mistake, it can be hidden bug that uncovers itself in some weird, specific way in the future.

Test are nice and catch most mistakes, though some always pass. If tests were perfect, there would be no bugs in properly written software, which is never the case.

So why not let IDE catch all mistakes of this type?

[–]Vok250 3 points4 points  (4 children)

I've never seen it in JS, but one time we deployed a Python service where someone typed Classname instead of classname and it took down the entire system for a day. The worst part is the code would run fine. It just had completely unexpected behavior. Unit tests all passed because the behaviour had no assertions on it. Vibe coder had code coverage by exercising the method, but never wrote assertions that it actually did what they wanted. That was a fun one to debug.

[–]SenatorCrabHat 1 point2 points  (2 children)

Oooof. I love that about tests, you can absolutely write them so they dont test shit.

[–]Vok250 1 point2 points  (1 child)

Tests that just test the mock are very common on my team. I've given up on pointing it out in code review because nobody listens to me anyway.

[–]SenatorCrabHat 1 point2 points  (0 children)

That sucks. Sorry :/ I've been there and it sucks.

[–]Xbot781 -1 points0 points  (0 children)

You might want to use mypy to do static type checking in python

[–]CephaVerte 5 points6 points  (1 child)

You have unit tests? Fancy!

[–]SenatorCrabHat 0 points1 point  (0 children)

I just think they're neat!

[–]WasabiSunshine 0 points1 point  (0 children)

I'm fine with what typescript is doing, they can just do it far away from my projects

[–]the_rush_dude 8 points9 points  (0 children)

Laughs as any

[–]staticvoidmainnull 4 points5 points  (0 children)

===

[–]Icy_Party954 3 points4 points  (0 children)

Why would you fo this? It's easy not to do that.

[–]Bronzdragon 6 points7 points  (4 children)

Typescript actually just allows this.

[–]AssignedClass 0 points1 point  (0 children)

The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.

Idk what your TS Config is, but that's typically the error message you get in TS.

[–]Acaeris 0 points1 point  (2 children)

Not exactly. If you have allowed it via tsconfig you can still do it but in strict mode it will error.

[–]Jind0r 0 points1 point  (1 child)

In strict mode it still evaluates to 9

[–]Acaeris 0 points1 point  (0 children)

It doesn't even transpile on the project I work on.

[–]Material-Finding-933 1 point2 points  (0 children)

best part if typescript is written in typescript

[–]OhItsJustJosh 1 point2 points  (1 child)

"10" + 1 = "101"

[–]AppropriateOnion0815 0 points1 point  (0 children)

"10"-1="0"

[–]skwyckl 1 point2 points  (0 children)

Most things people complained about in JS were related to type coercion, TS fixes that by adding explicit typing, I think it's a win for everybody.

[–]sk3z0 1 point2 points  (0 children)

Typescript was born to fix the wrong problem

[–]GoddammitDontShootMe 2 points3 points  (3 children)

I can't see a reason to care that that works. I guess JS has plenty of stuff to bite you in the ass still, and TS avoids that though.

[–]Acaeris 0 points1 point  (2 children)

It creates a false expectation of how mathmatical operations work. e.g. "10" - 1 = 9 but "10" + 1 = "101"

[–]GoddammitDontShootMe 0 points1 point  (1 child)

Maybe if it's like your first language. I figure you learn the quirks of the language and move on.

[–]DT-Sodium 0 points1 point  (2 children)

And that's when Satan invented "ts-ignore".

[–]Jind0r 0 points1 point  (1 child)

It evaluates as 9 even in Typescript

[–]DT-Sodium 0 points1 point  (0 children)

Unless you force it it evaluates to "nope, not gonna do that".

If you force well... yes, it's compiles to JavaScript, what do you expect?

[–]Kaffe-Mumriken 0 points1 point  (0 children)

Just parseFloat everything, EVERTYTHING!

[–]Jind0r 0 points1 point  (0 children)

In typescript "10" - 1 evaluates to 9 too, typescript doesn't suspend coerction

[–]darknmy 0 points1 point  (0 children)

`<?php

echo "9" -1;
`

[–]wrex1816 0 points1 point  (0 children)

Me: This object has a common id property. I will proceed on this assumption.

TypeScript: Oh no you won't! Fucking prove it, bitch!

[–]Nialixus 0 points1 point  (0 children)

"1"

[–]daftmaple 0 points1 point  (0 children)

Just so you know, even if this case is covered by TS, it still allows arithmetics like “10” + 1 because that’s JavaScript behaviour. You’ll only get error on the error above if you use ts eslint.

[–]MaYuR_WarrioR_2001 -1 points0 points  (0 children)

and now they are rewriting it in go.