↔️ Type Conversion
JavaScript can automatically convert data from one type to another when required (implicit type conversion), or you can manually convert the data yourself when needed (explicit type conversion).
❓ What is Type Conversion?
Type conversion means changing one data type into another, for example:
Number → String
Boolean → Number
String → Number
etc.
JavaScript has two types of conversions:
✈️ Types of Conversion
1. Implicit Type Conversion (Type Coercion)
JS automatically converts the type behind the scenes.
✔️ Examples:
➤ String + Number
"5" + 2 // "52" (Number → String)➤ Number + Boolean
2 + true // 3 (true → 1)➤ Subtraction / Multiplication / Division
"5" - 1 // 4 ("5" → Number)
"5" * 2 // 10
"5" / 2 // 2.5➤ Comparisons convert types
"5" == 5 // true (string → number)2. Explicit Type Conversion
You convert manually using built-in functions.
➤ Convert to Number
Syntax | Example | Result |
|---|---|---|
Number() |
| 20 |
parseInt() |
| 20 |
parseFloat() |
| 3.14 |
➤ Invalid conversion gives:
Number("abc") // NaN➤ Convert to String
Method | Example |
|---|---|
String() |
|
.toString() |
|
➤ Convert to Boolean
Falsy values become false, everything else → true.
Falsy Values: 0 "" (empty string) null undefined NaN false
Example:
Boolean(0) // false
Boolean("Hi") // true
Boolean([]) // true
Boolean({}) // true<div class="infographic-jsconv">
<style>
.infographic-jsconv {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--ok: #1a7f4e;
--ok-soft: #e3f5ec;
--err: #c0392b;
--err-soft: #fbe9e7;
--display-font: 'Fraunces', Georgia, serif;
--body-font: 'Inter', -apple-system, sans-serif;
--mono-font: 'IBM Plex Mono', 'Courier New', monospace;
max-width: 780px;
margin: 0 auto;
box-sizing: border-box;
font-family: var(--body-font);
color: var(--ink);
background: var(--paper);
}
.infographic-jsconv[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
--ok: #5cd6a0;
--ok-soft: #16342a;
--err: #e57373;
--err-soft: #3a2222;
}
.infographic-jsconv * { box-sizing: border-box; }
.infographic-jsconv .ig-inner { padding: 1.75rem clamp(1.25rem, 5vw, 3rem) 2rem; }
.infographic-jsconv .ig-title {
font-family: var(--display-font); font-size: clamp(1.4rem, 4.5vw, 1.9rem);
font-weight: 600; text-align: center; margin: 0 0 1.25rem;
}
.infographic-jsconv .tabs { display: flex; gap: 0.4rem; justify-content: center; flex-wrap: wrap; }
.infographic-jsconv .tab {
font: inherit; font-size: 0.8rem; font-weight: 600; border: 1px solid var(--line);
background: var(--paper); color: var(--ink-soft); padding: 0.4rem 0.9rem;
border-radius: 999px; cursor: pointer;
}
.infographic-jsconv .tab.is-active { background: var(--accent); color: var(--paper); border-color: var(--accent); }
.infographic-jsconv .chips { display: flex; flex-wrap: wrap; gap: 0.5rem; justify-content: center; margin-top: 1rem; }
.infographic-jsconv .chip {
font: inherit; font-size: 0.82rem; font-weight: 700; font-family: var(--mono-font);
border: 1px solid var(--line); background: var(--paper-alt); color: var(--ink);
padding: 0.4rem 0.85rem; border-radius: 6px; cursor: pointer;
}
.infographic-jsconv .chip.is-active { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }
.infographic-jsconv .playground {
margin-top: 2rem; background: var(--paper-alt); border: 1px solid var(--line);
padding: 2rem 1.25rem 1.5rem;
}
/* unified row: every direct child shares the same height and vertical center,
any auxiliary label (type tag / result type) is absolutely positioned so it
never affects the row's alignment */
.infographic-jsconv .row { display: flex; align-items: center; justify-content: center; gap: 0.6rem; flex-wrap: wrap; }
.infographic-jsconv .slot { position: relative; height: 2.7rem; display: flex; align-items: center; justify-content: center; }
.infographic-jsconv .slot-tag {
position: absolute; top: -1.5rem; left: 50%; transform: translateX(-50%);
font-size: 0.65rem; font-family: var(--mono-font); color: var(--accent);
background: var(--accent-soft); padding: 0.1rem 0.45rem; border-radius: 4px; white-space: nowrap;
}
.infographic-jsconv .slot-sub {
position: absolute; bottom: -1.4rem; left: 50%; transform: translateX(-50%);
font-size: 0.68rem; color: var(--ink-soft); white-space: nowrap;
}
.infographic-jsconv .type-pill {
font-family: var(--mono-font); font-size: 0.95rem; font-weight: 700;
padding: 0 1rem; height: 2.7rem; display: flex; align-items: center; justify-content: center;
background: var(--accent-soft); color: var(--accent); border-radius: 6px; min-width: 5.5rem;
}
.infographic-jsconv .type-pill.result {
background: var(--ok-soft); color: var(--ok); border: 1px solid var(--ok);
box-shadow: 0 3px 6px rgba(0,0,0,0.12);
}
.infographic-jsconv .val-input {
width: 6.5rem; height: 2.7rem; font-family: var(--mono-font); font-size: 0.95rem; text-align: center;
padding: 0 0.4rem; border: 1px solid var(--line); background: var(--paper);
color: var(--ink); outline: none;
}
.infographic-jsconv .val-input:focus { border-color: var(--accent); }
.infographic-jsconv .op-symbol,
.infographic-jsconv .eq-sign {
font-family: var(--mono-font); font-weight: 700; color: var(--accent);
min-width: 2rem;
}
.infographic-jsconv .eq-sign { color: var(--ink-soft); font-weight: 400; }
.infographic-jsconv .fn-label {
font-family: var(--mono-font); font-size: 1rem; font-weight: 700; color: var(--accent);
}
.infographic-jsconv .result-box {
font-family: var(--mono-font); font-size: 1.1rem; font-weight: 700;
height: 100%; display: flex; align-items: center; justify-content: center;
padding: 0 1rem; background: var(--ok-soft); color: var(--ok);
border: 1px solid var(--ok); border-radius: 6px; min-width: 5rem;
box-shadow: 0 3px 6px rgba(0,0,0,0.12);
}
.infographic-jsconv .result-box.is-error { background: var(--err-soft); color: var(--err); border-color: var(--err); }
.infographic-jsconv .falsy-row {
display: flex; gap: 0.4rem; justify-content: center; flex-wrap: wrap; margin-top: 2.1rem;
}
.infographic-jsconv .falsy-btn {
font: inherit; font-size: 0.72rem; font-family: var(--mono-font); border: 1px dashed var(--line);
background: var(--paper); color: var(--ink-soft); padding: 0.25rem 0.55rem; border-radius: 4px; cursor: pointer;
}
.infographic-jsconv .falsy-btn:hover { border-color: var(--accent); color: var(--accent); }
.infographic-jsconv .caption {
text-align: center; font-size: 0.85rem; color: var(--ink-soft); margin-top: 1.6rem; min-height: 1.2em;
}
.infographic-jsconv .caption strong { color: var(--ink); font-family: var(--mono-font); }
@media (prefers-reduced-motion: reduce) {
.infographic-jsconv *, .infographic-jsconv *::before, .infographic-jsconv *::after {
animation-duration: 0.001ms !important; transition-duration: 0.001ms !important;
}
}
</style>
<div class="ig-inner">
<h2 class="ig-title">Try it Yourself</h2>
<div class="tabs" id="tabs"></div>
<div class="chips" id="chips"></div>
<div class="playground">
<div class="row" id="row"></div>
<div class="falsy-row" id="falsyRow" style="display:none;"></div>
</div>
<p class="caption" id="caption"></p>
</div>
</div>
<script>
(function () {
const wrapper = document.currentScript.closest('.infographic-jsconv')
|| document.querySelector('.infographic-jsconv');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') {
dark = true;
} else if (bodyAttr === 'false') {
dark = false;
} else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
const IMPLICIT = [
{ id: 'plus1', sym: '+', a: '"5"', b: '2', example: '"5" + 2', caption: 'text stays, number joins as text' },
{ id: 'plus2', sym: '+', a: '2', b: 'true', example: '2 + true', caption: 'true becomes 1, then adds' },
{ id: 'minus', sym: '-', a: '"5"', b: '1', example: '"5" - 1', caption: 'text turns into a number first' },
{ id: 'mult', sym: '*', a: '"5"', b: '2', example: '"5" * 2', caption: 'text turns into a number first' },
{ id: 'div', sym: '/', a: '"5"', b: '2', example: '"5" / 2', caption: 'text turns into a number first' },
{ id: 'eq', sym: '==', a: '"5"', b: '5', example: '"5" == 5', caption: 'text turns into a number, then compares' }
];
const EXPLICIT = [
{ id: 'number', fn: 'Number', label: 'Number()', input: '"20"', caption: 'parses the whole value as a number' },
{ id: 'parseInt', fn: 'parseInt', label: 'parseInt()', input: '"20px"', caption: 'reads leading digits, stops at non-digits' },
{ id: 'parseFloat', fn: 'parseFloat', label: 'parseFloat()',input: '"3.14"', caption: 'like parseInt, but keeps the decimal' },
{ id: 'string', fn: 'String', label: 'String()', input: '100', caption: 'wraps any value as text' },
{ id: 'toString', fn: 'toString', label: '.toString()', input: '100', caption: 'same result, called on the value itself' },
{ id: 'boolean', fn: 'Boolean', label: 'Boolean()', input: '0', caption: 'falsy values become false, rest become true' }
];
function parseValue(raw) {
const t = (raw || '').trim();
if (t === '') return undefined;
if (t.length >= 2 && t[0] === '"' && t[t.length - 1] === '"') return t.slice(1, -1);
if (t === 'null') return null;
if (t === 'true') return true;
if (t === 'false') return false;
if (t === 'undefined') return undefined;
if (t === 'NaN') return NaN;
if (!isNaN(Number(t))) return Number(t);
return t;
}
function typeName(v) {
if (v === null) return 'Null';
if (typeof v === 'number' && Number.isNaN(v)) return 'NaN';
const t = typeof v;
return t.charAt(0).toUpperCase() + t.slice(1);
}
function formatVal(v) {
if (typeof v === 'string') return JSON.stringify(v);
if (typeof v === 'number' && Number.isNaN(v)) return 'NaN';
return String(v);
}
function computeImplicit(sym, a, b) {
switch (sym) {
case '+': return a + b;
case '-': return a - b;
case '*': return a * b;
case '/': return a / b;
case '==': return a == b;
}
}
function computeExplicit(fn, val) {
try {
switch (fn) {
case 'Number': return Number(val);
case 'parseInt': return parseInt(String(val), 10);
case 'parseFloat': return parseFloat(String(val));
case 'String': return String(val);
case 'toString':
if (val === null || val === undefined) throw new Error('no toString on null/undefined');
return val.toString();
case 'Boolean': return Boolean(val);
}
} catch (e) {
return { __error: true };
}
}
const tabsEl = wrapper.querySelector('#tabs');
const chipsEl = wrapper.querySelector('#chips');
const rowEl = wrapper.querySelector('#row');
const falsyRow = wrapper.querySelector('#falsyRow');
const caption = wrapper.querySelector('#caption');
let currentTab = 'Implicit';
let currentItem = IMPLICIT[0];
let inStr;
const FALSY = ['0', '""', 'null', 'undefined', 'NaN', 'false'];
function buildImplicitRow() {
rowEl.innerHTML = '';
const a = parseValue(currentItem.a);
const b = parseValue(currentItem.b);
let result;
try { result = computeImplicit(currentItem.sym, a, b); } catch (e) { result = undefined; }
const aSlot = document.createElement('div'); aSlot.className = 'slot';
aSlot.innerHTML = `<span class="type-pill">${formatVal(a)}</span>
<span class="slot-sub">${typeName(a)}</span>`;
const opSlot = document.createElement('div'); opSlot.className = 'slot';
opSlot.innerHTML = `<span class="op-symbol">${currentItem.sym}</span>`;
const bSlot = document.createElement('div'); bSlot.className = 'slot';
bSlot.innerHTML = `<span class="type-pill">${formatVal(b)}</span>
<span class="slot-sub">${typeName(b)}</span>`;
const eqSlot = document.createElement('div'); eqSlot.className = 'slot';
eqSlot.innerHTML = `<span class="eq-sign">=</span>`;
const resSlot = document.createElement('div'); resSlot.className = 'slot';
resSlot.innerHTML = `<span class="type-pill result">${formatVal(result)}</span>
<span class="slot-sub">${typeName(result)}</span>`;
rowEl.appendChild(aSlot); rowEl.appendChild(opSlot); rowEl.appendChild(bSlot);
rowEl.appendChild(eqSlot); rowEl.appendChild(resSlot);
falsyRow.style.display = 'none';
}
function buildExplicitRow() {
rowEl.innerHTML = '';
const fnSlot = document.createElement('div'); fnSlot.className = 'slot';
fnSlot.innerHTML = `<span class="fn-label">${currentItem.label}</span>`;
const inSlot = document.createElement('div'); inSlot.className = 'slot';
const inTag = document.createElement('span'); inTag.className = 'slot-tag'; inTag.id = 'inTag';
const inInputEl = document.createElement('input'); inInputEl.className = 'val-input'; inInputEl.id = 'inInput';
inInputEl.value = inStr;
inSlot.appendChild(inTag); inSlot.appendChild(inInputEl);
const eqSlot = document.createElement('div'); eqSlot.className = 'slot';
eqSlot.innerHTML = `<span class="eq-sign">→</span>`;
const resSlot = document.createElement('div'); resSlot.className = 'slot';
resSlot.innerHTML = `<span class="result-box" id="resultBox"></span><span class="slot-sub" id="resultType"></span>`;
rowEl.appendChild(fnSlot); rowEl.appendChild(inSlot); rowEl.appendChild(eqSlot); rowEl.appendChild(resSlot);
wrapper.querySelector('#inInput').addEventListener('input', (e) => { inStr = e.target.value; updateExplicit(); });
if (currentItem.fn === 'Boolean') {
falsyRow.style.display = 'flex';
falsyRow.innerHTML = '';
FALSY.forEach(v => {
const btn = document.createElement('button');
btn.className = 'falsy-btn'; btn.textContent = v || '""';
btn.addEventListener('click', () => {
inStr = v;
wrapper.querySelector('#inInput').value = v;
updateExplicit();
});
falsyRow.appendChild(btn);
});
} else {
falsyRow.style.display = 'none';
}
}
function updateExplicit() {
const val = parseValue(inStr);
wrapper.querySelector('#inTag').textContent = typeName(val);
const result = computeExplicit(currentItem.fn, val);
const resultBox = wrapper.querySelector('#resultBox');
const resultType = wrapper.querySelector('#resultType');
if (result && result.__error) {
resultBox.classList.add('is-error');
resultBox.textContent = 'Error';
resultType.textContent = 'TypeError';
} else {
resultBox.classList.remove('is-error');
resultBox.textContent = formatVal(result);
resultType.textContent = typeName(result);
}
caption.innerHTML = `<strong>${currentItem.label}</strong> — ${currentItem.caption}`;
}
function selectItem(item) {
currentItem = item;
wrapper.querySelectorAll('.chip').forEach(c => c.classList.toggle('is-active', c.dataset.id === item.id));
if (currentTab === 'Implicit') {
buildImplicitRow();
caption.innerHTML = `<strong>${item.example}</strong> — ${item.caption}`;
} else {
inStr = item.input;
buildExplicitRow();
updateExplicit();
}
}
function buildChips() {
chipsEl.innerHTML = '';
const list = currentTab === 'Implicit' ? IMPLICIT : EXPLICIT;
list.forEach((item, idx) => {
const chip = document.createElement('button');
chip.className = 'chip';
chip.textContent = currentTab === 'Implicit' ? item.example : item.label;
chip.dataset.id = item.id;
chip.addEventListener('click', () => selectItem(item));
chipsEl.appendChild(chip);
if (idx === 0) selectItem(item);
});
}
function selectTab(name) {
currentTab = name;
wrapper.querySelectorAll('.tab').forEach(t => t.classList.toggle('is-active', t.dataset.tab === name));
buildChips();
}
['Implicit', 'Explicit'].forEach(name => {
const tab = document.createElement('button');
tab.className = 'tab';
tab.textContent = name;
tab.dataset.tab = name;
tab.addEventListener('click', () => selectTab(name));
tabsEl.appendChild(tab);
});
selectTab('Implicit');
})();
</script>.demo {
font-family: system-ui, sans-serif;
padding: 16px;
}
.demo h1 {
color: #2563eb;
margin: 0 0 8px;
}
.demo p {
color: #4b5563;
margin: 0;
}document.querySelector('.demo h1')?.addEventListener('click', () => {
alert('Hello from live preview!');
});