Topic 1.5
Type Conversion
In one line
JavaScript converts values between types either when you ask (String(), Number(), Boolean(), parseInt, parseFloat) or automatically when an operator needs a different type; knowing the automatic rules prevents bugs like "5" + 1 giving "51".
Think of it like this
Changing money at an airport. You hand over rupees and ask for dollars: that's an explicit exchange, you chose it. But some shops quietly convert your money at their own rate when you pay with a card abroad: that's implicit, it happens without you asking, and the result can surprise you. JavaScript converts values between types in both ways.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- Type conversion
- Turning a value of one type into another, like
"42"into42. - Explicit conversion
- Converting on purpose with
String(),Number(),Boolean()and similar. - Coercion
- Automatic conversion JavaScript does because an operator needs a different type.
- parseInt
- Reads a whole number from the start of a string and stops at the first non-digit.
- parseFloat
- Like
parseIntbut keeps the decimal part. - Radix
- The number base: 10 for normal numbers, 16 for hexadecimal, 2 for binary.
- Falsy
- A value that becomes
falsewhen converted to boolean, like0or"". - Truthy
- Any value that becomes
truewhen converted to boolean. - Unary plus
- A
+in front of one value, like+"42", which converts it to a number.
Step by step
01Read a number from a form
Values from inputs are always strings, even when the input shows a number. Adding to them joins text.
const raw = qtyInput.value; // "5" (a string!)
raw + 1 // "51"
Number(raw) + 1 // 602Choose Number() or parseInt()
Number is strict about the whole string. parseInt and parseFloat read from the left and stop.
Number("42") // 42
Number("42px") // NaN
parseInt("42px", 10) // 42
parseFloat("1.5em") // 1.5
Number("") // 0 (careful!)
parseInt("", 10) // NaN03Convert to text
String() never throws for ordinary values, and gives readable text for primitives. Objects need a better plan, like JSON.stringify (Topic 6.6).
String(3.5) // "3.5"
String(null) // "null"
String([1, 2, 3]) // "1,2,3"
String({ a: 1 }) // "[object Object]"04Know what + does
JavaScript decides what + means by looking at both sides after turning objects into primitives.
05Other maths operators always want numbers
-, *, / and % convert both sides with the Number() rules, so text that isn't a clean number gives NaN.
"10" - "4" // 6
"10" * 2 // 20
"ten" * 2 // NaN
true + true // 206Convert at the edges
Convert input once, when it enters your program, and check the result (Number.isNaN). After that, every variable holds the type you expect and + behaves.
Try it yourself
- 1
Predict the joins
Before running the third example, add
console.log("2" + 2 * "2");. Hint:*happens before+. Write your prediction, then run. - 2
Blank input
In the form example, clear the box completely and press the button. It says
Next: 1. Why? (Look at whatNumber("")returns in the first example.) How would you treat an empty box as an error? - 3
Number vs parseInt
In the second example, try
Number("1e3")andparseInt("1e3", 10). Explain the difference.
Code & diagrams
Console
(nothing was printed)Expected console output
42 true null undefined
1,2,3 [object Object]
ff 101
42 12 0 NaN
1 0 0 NaN
26 0 5 NaN
3.5
false true false true true
true falseThe last line is a classic trap: the number becomes the string `"5e-7"` first, and parseInt stops at the `e`.
Console
(nothing was printed)Expected console output
12
3.14
3
NaN
42 NaN
255 5
5In the last line, `+"a"` is `NaN`, which is then joined as text.
Console
(nothing was printed)Expected console output
51
4
12
33
123
2
1 NaN
[object Object]
baNaNaType a different number (or a word) in the box and press the button. The `? :` used here is the ternary operator from Topic 2.3.
Preview
Console
Nothing logged yet.Expected console output
string
51
6Break it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Add two form values without converting
In a calculator, write out.textContent = a.value + b.value; with the inputs 2 and 3.
Break #2
Forget the radix
Use parseInt(input) on inputs like "0x10".
Myth vs fact
Myth
Number("") is NaN because the string is empty.
Fact
It's 0. Empty and whitespace-only strings convert to 0, which is why a blank form field can silently become 0. Check for empty input separately.
Myth
parseInt rounds decimals.
Fact
It truncates: it stops reading at the ., so parseInt("3.99", 10) is 3. Use Math.round(Number(x)) to round.
Myth
The string "false" is false.
Fact
Every non-empty string is truthy, including "false" and "0". Compare the text instead: value === "true".
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
ToPrimitive with hint "number" calls
valueOf()thentoString(); with hint "string" (template literals,String()),toString()first.+and==use the "default" hint, which behaves like "number" except forDateobjects, which prefer strings. An object can override all of this with aSymbol.toPrimitivemethod. - ▸
Number()and unary+accept0x,0o,0bprefixes,Infinity, exponent notation and surrounding whitespace, but not numeric separators:Number("1_000")isNaN. Underscores are allowed only in number literals in code. - ▸
Unary
+throws on a BigInt (+10nis a TypeError), butNumber(10n)works. That's one of the few places where+xandNumber(x)differ. - ▸
Coercion is spec-defined and predictable, not random: the abstract operations ToString, ToNumber, ToBoolean and ToPrimitive in the ECMAScript spec define every case. Linters (ESLint) and TypeScript catch most accidental coercion before it ships.
Remember this
- 1
Type conversion means turning a value of one type into another, like the string
"42"into the number42. When you do it on purpose it's explicit conversion. When JavaScript does it automatically because an operator needs a certain type, it's implicit conversion, usually called coercion. There are only three target types that matter: string, number and boolean. - 2
To string:
String(value)works on everything:String(42)is"42",String(null)is"null",String([1, 2])is"1,2", and a plain object becomes"[object Object]", which is almost never what you want. Template literals convert the same way. Numbers also havetoString(base):(255).toString(16)is"ff". - 3
To number:
Number(value)reads the whole string or fails. Spaces at the ends are ignored, an empty or blank string becomes0, and anything with stray characters becomesNaN:Number("12px")isNaN.truebecomes1,falseandnullbecome0,undefinedbecomesNaN. The unary plus+valuedoes exactly the same asNumber(value). Everything you read from a form field (input.value) is a string, so you must convert it before doing maths. - 4
parseInt(string, radix)andparseFloat(string)are more forgiving: they read digits from the start and stop at the first character they don't understand.parseInt("12px")is12,parseFloat("3.14abc")is3.14,parseInt("3.99")is3(it cuts, it doesn't round). If no digits come first, the result isNaN. The radix is the number base: always pass10for normal numbers (parseInt("08", 10)), or16for hex,2for binary. UseNumber()when the whole input must be a valid number, andparseInt/parseFloatwhen you want to pull a number off the front of text like"20px". - 5
To boolean:
Boolean(value)returnsfalsefor exactly eight falsy values (false,0,-0,0n,"",null,undefined,NaN) andtruefor everything else, including"0","false"," ",[]and{}. Writing!!value(not-not) is a common short form. Topic 1.6 uses these rules forifconditions. - 6
Implicit coercion follows operator rules. The
+operator joins if either side is a string, so"5" + 1is"51"and1 + 2 + "3"is"33"(left to right:1 + 2is3, then3 + "3"joins). The other maths operators (-,*,/,%) only work on numbers, so they convert both sides:"5" - 1is4,"3" * "4"is12. Objects are first turned into a primitive (a step called ToPrimitive, which calls the object'svalueOf()andtoString()methods): that's why[] + {}is"[object Object]". The safe habit: convert explicitly at the edges of your program (form inputs, URLs, API data), then work with the right types inside.
Explain it without notes
What is the difference between explicit conversion and coercion? Give an example of each.
When would you use Number() and when parseInt()/parseFloat()?
Explain the outputs of "5" + 1, "5" - 1 and 1 + 2 + "3".
Which values are falsy?
Practice
Convert the strings "19.5" and "0.5" to numbers and log their sum, which must be 20.
Read the width out of "240px" as a number, double it, and log 480px.
Predict, then check: "7" * "6", "7" + "6", "7" - - "6".
Trade-offs
- ↔
Explicit conversion is longer to write but makes intent obvious and catches bad input early; relying on coercion is shorter but hides bugs until a string sneaks in.
- ↔
Number()rejects partial input (safer for validation),parseFloattolerates units (handier for CSS values); pick by whether stray characters should be an error.
Done when you can
I can convert values with
String(),Number()andBoolean().I can choose between
Number()andparseInt/parseFloat, and I always pass a radix.I can predict what
+,-and*do with strings.I convert form input to numbers before doing maths.
I can list the falsy values.