Type Conversion
Type conversion is the process of converting one data type to another. JavaScript performs type conversion in two ways: implicit (automatic) and explicit (manual). Understanding both is crucial for writing predictable code.
Types of Conversion
1. Implicit Conversion (Type Coercion)
JavaScript automatically converts types when needed:
javascriptconsole.log("5" + 3); // "53" - number to string console.log("5" - 3); // 2 - string to number console.log(true + 1); // 2 - boolean to number
2. Explicit Conversion (Type Casting)
You manually convert types using built-in functions:
javascriptconsole.log(Number("5")); // 5 - string to number console.log(String(123)); // "123" - number to string console.log(Boolean(1)); // true - number to boolean
String Conversion
Implicit String Conversion
JavaScript converts values to strings when:
- •Using the
+
operator with a string - •Template literals
- •Certain methods expect strings
javascript// + operator with strings console.log("The answer is " + 42); // "The answer is 42" console.log("Score: " + true); // "Score: true" console.log("Value: " + null); // "Value: null" console.log("Result: " + undefined); // "Result: undefined" // Template literals let age = 25; console.log(`I am ${age} years old`); // "I am 25 years old" // Array to string let fruits = ["apple", "banana", "orange"]; console.log("Fruits: " + fruits); // "Fruits: apple,banana,orange" // Object to string let person = { name: "John", age: 30 }; console.log("Person: " + person); // "Person: [object Object]"
Explicit String Conversion
javascript// String() function console.log(String(123)); // "123" console.log(String(true)); // "true" console.log(String(null)); // "null" console.log(String(undefined)); // "undefined" // toString() method (not available for null/undefined) let num = 123; console.log(num.toString()); // "123" console.log(true.toString()); // "true" // toString() with radix (base) let number = 255; console.log(number.toString(2)); // "11111111" (binary) console.log(number.toString(8)); // "377" (octal) console.log(number.toString(16)); // "ff" (hexadecimal) // JSON.stringify for objects let obj = { name: "Alice", age: 28 }; console.log(JSON.stringify(obj)); // '{"name":"Alice","age":28}' // Custom toString for objects let product = { name: "Laptop", price: 999, toString() { return `${this.name}: $${this.price}`; } }; console.log(String(product)); // "Laptop: $999"
Number Conversion
Implicit Number Conversion
JavaScript converts to numbers when:
- •Using arithmetic operators (except
+
with strings) - •Comparison operators
- •Mathematical functions
javascript// Arithmetic operators console.log("10" - 5); // 5 console.log("10" * 2); // 20 console.log("10" / 2); // 5 console.log("10" % 3); // 1 // Unary + operator console.log(+"123"); // 123 console.log(+true); // 1 console.log(+false); // 0 console.log(+null); // 0 console.log(+undefined); // NaN console.log(+""); // 0 console.log(+" "); // 0 console.log(+"123abc"); // NaN // Comparison operators console.log("10" > 5); // true console.log("10" == 10); // true (loose equality) // Logical NOT operator (double negation) console.log(!!123); // true console.log(!!""); // false
Explicit Number Conversion
javascript// Number() function console.log(Number("123")); // 123 console.log(Number("123.45")); // 123.45 console.log(Number("")); // 0 console.log(Number(" ")); // 0 console.log(Number("123abc")); // NaN console.log(Number(true)); // 1 console.log(Number(false)); // 0 console.log(Number(null)); // 0 console.log(Number(undefined)); // NaN // parseInt() - converts to integer console.log(parseInt("123")); // 123 console.log(parseInt("123.45")); // 123 (truncates decimal) console.log(parseInt("123abc")); // 123 (stops at first non-digit) console.log(parseInt("abc123")); // NaN (starts with non-digit) console.log(parseInt(" 123 ")); // 123 (ignores whitespace) // parseInt() with radix console.log(parseInt("1010", 2)); // 10 (binary to decimal) console.log(parseInt("ff", 16)); // 255 (hex to decimal) console.log(parseInt("77", 8)); // 63 (octal to decimal) // parseFloat() - converts to floating-point number console.log(parseFloat("123.45")); // 123.45 console.log(parseFloat("123.45abc")); // 123.45 console.log(parseFloat("abc123.45")); // NaN // Math functions for conversion console.log(Math.floor(123.89)); // 123 console.log(Math.ceil(123.11)); // 124 console.log(Math.round(123.5)); // 124 console.log(Math.trunc(123.89)); // 123 (removes decimal part)
Number Validation
javascript// Check if conversion resulted in valid number function safeNumberConversion(value) { let num = Number(value); if (isNaN(num)) { return { success: false, error: "Not a valid number" }; } if (!isFinite(num)) { return { success: false, error: "Number is infinite" }; } return { success: true, value: num }; } // Test the function console.log(safeNumberConversion("123")); // { success: true, value: 123 } console.log(safeNumberConversion("abc")); // { success: false, error: "Not a valid number" } console.log(safeNumberConversion("Infinity")); // { success: false, error: "Number is infinite" }
Boolean Conversion
Implicit Boolean Conversion
JavaScript converts to boolean in:
- •Conditional statements (
if
,while
, etc.) - •Logical operators (
&&
,||
,!
) - •Ternary operator
javascript// Falsy values (convert to false) if (false) console.log("Won't run"); if (0) console.log("Won't run"); if (-0) console.log("Won't run"); if (0n) console.log("Won't run"); // BigInt zero if ("") console.log("Won't run"); if (null) console.log("Won't run"); if (undefined) console.log("Won't run"); if (NaN) console.log("Won't run"); // Truthy values (everything else converts to true) if (true) console.log("Will run"); if (1) console.log("Will run"); if (-1) console.log("Will run"); if ("hello") console.log("Will run"); if ("0") console.log("Will run"); // Non-empty string if ([]) console.log("Will run"); // Empty array if ({}) console.log("Will run"); // Empty object if (function(){}) console.log("Will run"); // Function // Logical operators let user = null; let defaultUser = user || "Guest"; // "Guest" (user is falsy) let settings = { theme: "dark" }; let theme = settings && settings.theme; // "dark" (settings is truthy)
Explicit Boolean Conversion
javascript// Boolean() function console.log(Boolean(1)); // true console.log(Boolean(0)); // false console.log(Boolean("hello")); // true console.log(Boolean("")); // false console.log(Boolean([])); // true console.log(Boolean({})); // true console.log(Boolean(null)); // false console.log(Boolean(undefined)); // false // Double negation (!!) - common shorthand console.log(!!1); // true console.log(!!"hello"); // true console.log(!!""); // false console.log(!!null); // false // Practical usage function isValidInput(input) { return Boolean(input && input.trim()); } console.log(isValidInput("hello")); // true console.log(isValidInput(" ")); // false console.log(isValidInput("")); // false console.log(isValidInput(null)); // false
Array and Object Conversion
Array Conversion
javascript// Array to string let fruits = ["apple", "banana", "orange"]; console.log(String(fruits)); // "apple,banana,orange" console.log(fruits.toString()); // "apple,banana,orange" console.log(fruits.join(", ")); // "apple, banana, orange" console.log(fruits.join(" | ")); // "apple | banana | orange" // Array to number (usually NaN) console.log(Number([])); // 0 (empty array) console.log(Number([5])); // 5 (single number element) console.log(Number([1, 2])); // NaN (multiple elements) console.log(Number(["hello"])); // NaN (non-numeric element) // String to array let text = "hello,world,javascript"; console.log(text.split(",")); // ["hello", "world", "javascript"] console.log(text.split("")); // ["h", "e", "l", "l", "o", ",", "w", ...] console.log([...text]); // ["h", "e", "l", "l", "o", ",", "w", ...] // Array.from() for conversion console.log(Array.from("hello")); // ["h", "e", "l", "l", "o"] console.log(Array.from({length: 3}, (_, i) => i)); // [0, 1, 2] // Converting array-like objects function example() { let args = Array.from(arguments); // Convert arguments to array return args; } console.log(example(1, 2, 3)); // [1, 2, 3]
Object Conversion
javascript// Object to string let person = { name: "John", age: 30 }; console.log(String(person)); // "[object Object]" console.log(person.toString()); // "[object Object]" // Better object to string conversion console.log(JSON.stringify(person)); // '{"name":"John","age":30}' // Custom toString method let product = { name: "Laptop", price: 999, toString() { return `${this.name}: $${this.price}`; } }; console.log(String(product)); // "Laptop: $999" // Object to number (usually NaN) console.log(Number({})); // NaN console.log(Number({valueOf: () => 42})); // 42 (custom valueOf) // Object to boolean (always true for objects) console.log(Boolean({})); // true console.log(Boolean([])); // true console.log(Boolean(new Date())); // true // String to object let jsonString = '{"name":"Alice","age":25}'; console.log(JSON.parse(jsonString)); // {name: "Alice", age: 25} // Object.entries() and Object.fromEntries() let obj = { a: 1, b: 2, c: 3 }; let entries = Object.entries(obj); // [["a", 1], ["b", 2], ["c", 3]] let backToObj = Object.fromEntries(entries); // {a: 1, b: 2, c: 3}
Common Conversion Patterns
1. Form Data Processing
javascript// Simulating form data (always strings) let formData = { name: "John Doe", age: "30", salary: "50000.50", isActive: "true", hobbies: "reading,swimming,coding" }; // Convert form data to appropriate types function processFormData(data) { return { name: String(data.name).trim(), age: parseInt(data.age, 10), salary: parseFloat(data.salary), isActive: data.isActive === "true", hobbies: data.hobbies.split(",").map(hobby => hobby.trim()) }; } let processedData = processFormData(formData); console.log(processedData); // { // name: "John Doe", // age: 30, // salary: 50000.5, // isActive: true, // hobbies: ["reading", "swimming", "coding"] // }
2. API Response Processing
javascript// API often returns strings that need conversion let apiResponse = { id: "123", timestamp: "1640995200000", price: "99.99", inStock: "1", tags: "electronics,laptop,computer" }; function normalizeApiResponse(response) { return { id: parseInt(response.id, 10), timestamp: new Date(parseInt(response.timestamp, 10)), price: parseFloat(response.price), inStock: Boolean(parseInt(response.inStock, 10)), tags: response.tags.split(",") }; } let normalizedData = normalizeApiResponse(apiResponse); console.log(normalizedData);
3. URL Parameter Processing
javascript// URL parameters are always strings function parseUrlParams(url) { let params = new URLSearchParams(url.split("?")[1]); let result = {}; for (let [key, value] of params) { // Try to convert to appropriate type if (value === "true" || value === "false") { result[key] = value === "true"; } else if (!isNaN(value) && !isNaN(parseFloat(value))) { result[key] = parseFloat(value); } else { result[key] = value; } } return result; } let url = "https://example.com/search?q=laptop&page=2&inStock=true&minPrice=100.50"; console.log(parseUrlParams(url)); // { q: "laptop", page: 2, inStock: true, minPrice: 100.5 }
Type Conversion Pitfalls
1. Equality Comparisons
javascript// Problematic loose equality (==) console.log(0 == false); // true console.log("" == false); // true console.log(null == undefined); // true console.log("0" == 0); // true console.log([1] == 1); // true console.log([1,2] == "1,2"); // true // Better strict equality (===) console.log(0 === false); // false console.log("" === false); // false console.log(null === undefined); // false console.log("0" === 0); // false console.log([1] === 1); // false console.log([1,2] === "1,2"); // false // When loose equality might be acceptable let userInput = "5"; if (userInput == 5) { // Might be OK for user input console.log("User entered 5"); } // But explicit conversion is clearer if (Number(userInput) === 5) { // Better - explicit intent console.log("User entered 5"); }
2. Addition vs Concatenation
javascript// Confusing behavior with + console.log(1 + 2); // 3 (addition) console.log("1" + 2); // "12" (concatenation) console.log(1 + "2"); // "12" (concatenation) console.log("1" + "2"); // "12" (concatenation) // Mixed operations console.log(1 + 2 + "3"); // "33" (1+2=3, then "3"+"3") console.log("1" + 2 + 3); // "123" ("1"+"2"="12", then "12"+"3") // Solutions console.log(Number("1") + 2); // 3 (explicit conversion) console.log(parseInt("1", 10) + 2); // 3 (explicit conversion) console.log(+"1" + 2); // 3 (unary + conversion) // Template literals for string building let a = 1, b = 2; console.log(`Result: ${a + b}`); // "Result: 3"
3. Falsy Value Confusion
javascript// All these are falsy, but different console.log(Boolean(0)); // false console.log(Boolean("")); // false console.log(Boolean(null)); // false console.log(Boolean(undefined)); // false console.log(Boolean(NaN)); // false // But they're not equal to each other console.log(0 === ""); // false console.log(null === undefined); // false console.log(0 === null); // false // Be specific in checks function isEmptyString(value) { return value === ""; // Only empty string } function isNullOrUndefined(value) { return value == null; // Both null and undefined } function isFalsy(value) { return !value; // Any falsy value }
Safe Conversion Utilities
1. Safe Number Conversion
javascriptfunction toNumber(value, defaultValue = 0) { if (value === null || value === undefined) { return defaultValue; } let num = Number(value); if (isNaN(num) || !isFinite(num)) { return defaultValue; } return num; } // Usage console.log(toNumber("123")); // 123 console.log(toNumber("abc")); // 0 console.log(toNumber("abc", -1)); // -1 console.log(toNumber(null)); // 0 console.log(toNumber(undefined, 100)); // 100 function toInteger(value, defaultValue = 0) { let num = toNumber(value, defaultValue); return Math.trunc(num); } console.log(toInteger("123.45")); // 123 console.log(toInteger("abc", -1)); // -1
2. Safe String Conversion
javascriptfunction toString(value, defaultValue = "") { if (value === null || value === undefined) { return defaultValue; } if (typeof value === "object") { try { return JSON.stringify(value); } catch (e) { return String(value); } } return String(value); } // Usage console.log(toString(123)); // "123" console.log(toString(null)); // "" console.log(toString(null, "N/A")); // "N/A" console.log(toString({name: "John"})); // '{"name":"John"}'
3. Safe Boolean Conversion
javascriptfunction toBoolean(value, truthyStrings = ["true", "yes", "1"]) { if (typeof value === "boolean") { return value; } if (typeof value === "string") { return truthyStrings.includes(value.toLowerCase()); } return Boolean(value); } // Usage console.log(toBoolean(true)); // true console.log(toBoolean("true")); // true console.log(toBoolean("yes")); // true console.log(toBoolean("false")); // false console.log(toBoolean("no")); // false console.log(toBoolean(1)); // true console.log(toBoolean(0)); // false
Practical Examples
1. Configuration Parser
javascript// Parse configuration from various sources function parseConfig(rawConfig) { let config = {}; for (let [key, value] of Object.entries(rawConfig)) { // Handle different value types if (typeof value === "string") { // Try to parse as JSON first try { config[key] = JSON.parse(value); } catch (e) { // Handle special string values if (value.toLowerCase() === "true") { config[key] = true; } else if (value.toLowerCase() === "false") { config[key] = false; } else if (!isNaN(value) && value.trim() !== "") { config[key] = Number(value); } else { config[key] = value; } } } else { config[key] = value; } } return config; } // Test with environment variables (always strings) let envConfig = { PORT: "3000", DEBUG: "true", MAX_CONNECTIONS: "100", ALLOWED_ORIGINS: '["localhost", "example.com"]', DATABASE_URL: "mongodb://localhost:27017/myapp" }; console.log(parseConfig(envConfig)); // { // PORT: 3000, // DEBUG: true, // MAX_CONNECTIONS: 100, // ALLOWED_ORIGINS: ["localhost", "example.com"], // DATABASE_URL: "mongodb://localhost:27017/myapp" // }
2. Data Sanitizer
javascript// Sanitize and convert user input function sanitizeUserData(data, schema) { let sanitized = {}; for (let [field, rules] of Object.entries(schema)) { let value = data[field]; // Apply type conversion switch (rules.type) { case "string": value = toString(value, rules.default || ""); if (rules.trim) value = value.trim(); if (rules.maxLength) value = value.substring(0, rules.maxLength); break; case "number": value = toNumber(value, rules.default || 0); if (rules.min !== undefined) value = Math.max(value, rules.min); if (rules.max !== undefined) value = Math.min(value, rules.max); break; case "boolean": value = toBoolean(value); break; case "array": if (typeof value === "string") { value = value.split(rules.separator || ",").map(item => item.trim()); } else if (!Array.isArray(value)) { value = rules.default || []; } break; } sanitized[field] = value; } return sanitized; } // Usage let userInput = { name: " John Doe ", age: "30", email: "john@example.com", isActive: "true", hobbies: "reading, swimming, coding", score: "150" // Will be clamped }; let schema = { name: { type: "string", trim: true, maxLength: 50 }, age: { type: "number", min: 0, max: 120 }, email: { type: "string", trim: true }, isActive: { type: "boolean" }, hobbies: { type: "array", separator: "," }, score: { type: "number", min: 0, max: 100 } }; console.log(sanitizeUserData(userInput, schema)); // { // name: "John Doe", // age: 30, // email: "john@example.com", // isActive: true, // hobbies: ["reading", "swimming", "coding"], // score: 100 // }
Best Practices
1. Be Explicit
javascript// Poor - relies on implicit conversion if (userAge) { // What if userAge is 0? } // Better - explicit check if (userAge !== null && userAge !== undefined) { // Clear intent } // Or use nullish coalescing let age = userAge ?? 0;
2. Validate After Conversion
javascriptfunction processAge(input) { let age = Number(input); if (isNaN(age)) { throw new Error("Age must be a number"); } if (age < 0 || age > 150) { throw new Error("Age must be between 0 and 150"); } return age; }
3. Use Type Guards
javascriptfunction isString(value) { return typeof value === "string"; } function isNumber(value) { return typeof value === "number" && !isNaN(value) && isFinite(value); } function isValidEmail(value) { return isString(value) && value.includes("@") && value.length > 3; } // Usage function processUser(userData) { if (!isString(userData.name)) { throw new Error("Name must be a string"); } if (!isNumber(userData.age)) { throw new Error("Age must be a valid number"); } if (!isValidEmail(userData.email)) { throw new Error("Email must be valid"); } // Process the data... }
Practice Exercises
javascript// Exercise 1: Create a universal converter function convert(value, targetType) { switch (targetType.toLowerCase()) { case "string": return toString(value); case "number": return toNumber(value); case "boolean": return toBoolean(value); case "array": if (Array.isArray(value)) return value; if (typeof value === "string") return value.split(","); return [value]; default: return value; } } // Test the converter console.log(convert("123", "number")); // 123 console.log(convert(123, "string")); // "123" console.log(convert("true", "boolean")); // true console.log(convert("a,b,c", "array")); // ["a", "b", "c"] // Exercise 2: Build a form validator function validateForm(formData, rules) { let errors = []; let validData = {}; for (let [field, rule] of Object.entries(rules)) { let value = formData[field]; // Required field check if (rule.required && (value === undefined || value === null || value === "")) { errors.push(`${field} is required`); continue; } // Type conversion and validation try { switch (rule.type) { case "email": value = String(value).trim().toLowerCase(); if (!value.includes("@")) { errors.push(`${field} must be a valid email`); } break; case "age": value = parseInt(value, 10); if (isNaN(value) || value < 0 || value > 150) { errors.push(`${field} must be a valid age (0-150)`); } break; case "phone": value = String(value).replace(/D/g, ""); // Remove non-digits if (value.length !== 10) { errors.push(`${field} must be a 10-digit phone number`); } break; } validData[field] = value; } catch (e) { errors.push(`Error processing ${field}: ${e.message}`); } } return { isValid: errors.length === 0, errors, data: validData }; } // Test the validator let form = { name: "John Doe", email: "JOHN@EXAMPLE.COM", age: "30", phone: "(555) 123-4567" }; let validationRules = { name: { required: true, type: "string" }, email: { required: true, type: "email" }, age: { required: true, type: "age" }, phone: { required: false, type: "phone" } }; console.log(validateForm(form, validationRules));
What's Next?
Excellent work! You now understand how JavaScript handles type conversion, both implicit and explicit. In the next lesson, we'll explore Operators - the symbols and keywords that allow you to perform operations on your data:
- •Arithmetic operators for mathematical calculations
- •Comparison operators for making decisions
- •Logical operators for combining conditions
- •Assignment operators for updating variables
- •And many more!
Key Takeaways
- •JavaScript performs automatic type conversion (coercion) in many situations
- •Use explicit conversion functions (
Number()
,String()
,Boolean()
) for clarity - •Be careful with the
+
operator - it can add or concatenate depending on types - •Use strict equality (
===
) to avoid unexpected type coercion - •Validate data after conversion to ensure it meets your requirements
- •Create utility functions for safe, predictable type conversion
- •Always consider edge cases like
null
,undefined
, andNaN
Understanding type conversion is essential for writing robust JavaScript applications that handle user input and external data correctly!