Dos tipos de coerción
JavaScript es muy flexible con los tipos. Cuando un operador recibe un valor del tipo "equivocado", el lenguaje no lanza un error: lo convierte. A eso se le llama coerción de tipos en JavaScript, y existe en dos variantes:
- Explícita — tú la pides:
Number("42"),String(99),Boolean(value). - Implícita — un operador la dispara sin que escribas ninguna conversión:
"5" - 2,"" == 0,if (value).
Al final, las dos acaban aplicando las mismas reglas de conversión por debajo. Lo único que cambia es quién toma la decisión: tú o el lenguaje. Casi todos los resultados raros de JavaScript — "5" + 1 === "51", [] == false, null == undefined — vienen de una coerción implícita que te pilla con la guardia baja.
El modelo mental es sencillo: si escribes Number(...) o String(...), sabes exactamente qué estás pidiendo. Si no lo haces, cada operador tiene su propia opinión sobre qué hacer con los valores, y ahí es donde se esconden los bugs.
Los tres tipos de destino en la coerción
La coerción de tipos en JavaScript siempre convierte hacia uno de estos tres tipos primitivos: string, number o boolean. (Existe un cuarto, bigint, pero nunca recibe coerción automática desde otros tipos.) Todo el resto de reglas se deriva de cuál de estos destinos busca cada operador.
La coerción a string es la más permisiva: todo valor tiene su forma en string. Fíjate que los objetos se convierten en el poco útil "[object Object]", y por eso cuando logueas un objeto concatenado con un string ("user: " + user) casi nunca ves lo que esperabas. Mejor usa JSON.stringify o template literals apuntando a campos concretos.
Coerción a number en JavaScript
La coerción a number es más estricta. Los strings tienen que parecerse de verdad a un número, o termina devolviéndote NaN:
Las sorpresas entre paréntesis son las que conviene memorizar:
- Una cadena vacía o con solo espacios se convierte en
0, no enNaN. nullpasa a ser0, peroundefinedse vuelveNaN.- Un array vacío se convierte en
0; un array con un solo elemento coacciona ese elemento; un array con varios elementos daNaN.
Si lo que quieres es extraer un número de un string que contiene otros caracteres, usa parseInt o parseFloat en lugar de Number:
Pasa siempre la base (10) a parseInt. Si la omites, las cadenas que empiezan por "0x" se interpretan como hexadecimal, algo que rara vez es lo que buscas.
Coerción a boolean en JavaScript
La coerción a boolean es la más sencilla de las tres. Hay una lista corta de valores que se convierten en false; todo lo demás pasa a ser true.
Los valores falsy son:
false0,-0,0n""(cadena vacía)nullundefinedNaN
Y ya está. Cualquier otro valor —incluidos "false", "0", [] y {}— es truthy.
Los resultados con arrays y objetos vacíos suelen confundir a quienes vienen de Python, donde las colecciones vacías son falsy. En JavaScript son truthy — así que, si quieres saber "¿este array está vacío?", compruébalo de forma explícita con arr.length === 0.
La coerción a boolean ocurre cada vez que un valor aparece en un contexto donde se espera un booleano: if (...), while (...), el operador ternario ? : y los operadores lógicos &&, ||, !.
El operador + en JavaScript: un caso especial
La mayoría de los operadores aritméticos convierten sus operandos a número. El + es la excepción: si alguno de los dos lados es un string, el + hace concatenación de cadenas. En cualquier otro caso, realiza una suma numérica.
La evaluación va de principio a fin. En 1 + 2 + "3", primero se calcula 1 + 2 = 3 y después 3 + "3" = "33". En cambio, "1" + 2 + 3 arranca como string y así se queda: primero "12", luego "123".
Por eso armar strings con + es poco confiable. Las template literals no tienen este problema:
El template literal evalúa count + 1 como una expresión numérica independiente y luego interpola el resultado. Sin sorpresas de coerción.
Usa conversiones explícitas
Cuando necesites convertir un tipo, dilo claramente. Te cuesta un par de caracteres más, pero elimina cualquier ambigüedad para quien lea tu código después:
Lo mismo pasa con los booleanos. !!value funciona y se ve por todos lados, pero Boolean(value) deja claro qué hace:
Una regla razonable: usa conversiones explícitas en la lógica de tu aplicación y reserva las formas cortas (+x, !!x) para los casos en los que la brevedad importa y la intención queda clara por el contexto.
El operador == se apoya fuerte en la coerción
Los operadores de igualdad son la mayor fuente de sorpresas relacionadas con la coerción. == aplica coerción antes de comparar; === no.
Cada true de arriba es el resultado de una cadena de coerción con varios pasos que la mayoría de los desarrolladores no sabríamos recitar de memoria. Ahí está el problema: el código que funciona por accidente es código que tarde o temprano se rompe. En la siguiente página veremos las reglas completas de igualdad; por ahora, la conclusión es simple: usa === por defecto y reserva == únicamente para el modismo x == null (que atrapa tanto null como undefined de un solo golpe).
Juntando las piezas
Un ejemplo práctico que muestra cuándo la coerción ayuda y cuándo te complica la vida:
Fíjate en la segunda llamada. Number("") devuelve 0, no NaN, así que parsePrice("") acaba devolviendo 0, que seguramente no es lo que esperaría quien use esta función. Si quieres rechazar una entrada vacía, añade una comprobación explícita:
Saber qué valores se convierten a 0 y cuáles a NaN es justo el tipo de detalle que te ahorra un bug sutil más adelante.
Lo que te conviene llevarte
- La coerción convierte a string, number o boolean según el operador que uses.
- El operador
+con cualquier string se vuelve concatenación; el resto de operadores aritméticos fuerzan conversión a number. - Los valores falsy son una lista corta y cerrada: apréndetela de memoria. Todo lo demás es truthy, incluidos
[]y{}. Number("")da0,Number([])da0,Number(null)da0… peroNumber(undefined)daNaN. Estos casos aparecen en bugs reales.- Usa
Number(x),String(x)yBoolean(x)antes que trucos implícitos ingeniosos. Tu yo del futuro te lo agradecerá.
Siguiente paso: operadores de igualdad
Todo lo que hace la coerción en las comparaciones vive dentro de ==. La próxima página compara == vs === vs Object.is, muestra el único caso donde == todavía resulta útil, y explica por qué los linters marcan por defecto la forma débil.
Preguntas frecuentes
¿Qué es la coerción de tipos en JavaScript?
La coerción de tipos es la conversión automática que hace JavaScript entre tipos: un número que pasa a string, un string que pasa a número o cualquier valor convertido a booleano. Ocurre de forma implícita cuando operadores como +, == o un if reciben un valor del tipo que no esperaban, y de forma explícita cuando eres tú quien llama a Number(x), String(x) o Boolean(x).
¿Cuál es la diferencia entre coerción implícita y explícita?
La coerción explícita es cuando tú, a propósito, llamas a una función de conversión: Number("42"), String(99), Boolean(value). La implícita es la que dispara un operador a tus espaldas: "5" - 2 da 3, pero "5" + 2 da "52". La explícita es legible y predecible; la implícita es la culpable de casi todos esos bugs del estilo "¿por qué me sale NaN?".
¿Cómo convierto un string a número en JavaScript?
Usa Number("42") para una conversión estricta (devuelve NaN si el string no es un número válido), o parseInt("42px", 10) / parseFloat("3.14em") cuando quieras extraer el número del principio de un string más sucio. El operador unario + (+"42") hace lo mismo que Number(), pero pasa más desapercibido al leer el código.
¿Por qué [] + [] devuelve un string vacío?
[] + [] devuelve un string vacío?El operador + no tiene ninguna operación numérica lógica entre dos arrays, así que JavaScript coerciona ambos a string. Los arrays se convierten a string uniendo sus elementos con comas, y un array vacío se queda en "". Por eso [] + [] acaba siendo "" + "", que es "". Un truco curioso para sorprender a alguien, y un buen motivo para no fiarte nunca de + con valores no primitivos.