Menu

Coerción de tipos en JavaScript: implícita vs explícita

Cómo convierte JavaScript los valores entre tipos: las reglas implícitas que nos hacen caer a todos, las conversiones explícitas que deberías usar y cuándo entra en juego cada una.

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.

index.js
Output
Click Run to see the output here.

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.

index.js
Output
Click Run to see the output here.

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:

index.js
Output
Click Run to see the output here.

Las sorpresas entre paréntesis son las que conviene memorizar:

  • Una cadena vacía o con solo espacios se convierte en 0, no en NaN.
  • null pasa a ser 0, pero undefined se vuelve NaN.
  • Un array vacío se convierte en 0; un array con un solo elemento coacciona ese elemento; un array con varios elementos da NaN.

Si lo que quieres es extraer un número de un string que contiene otros caracteres, usa parseInt o parseFloat en lugar de Number:

index.js
Output
Click Run to see the output here.

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:

  • false
  • 0, -0, 0n
  • "" (cadena vacía)
  • null
  • undefined
  • NaN

Y ya está. Cualquier otro valor —incluidos "false", "0", [] y {}— es truthy.

index.js
Output
Click Run to see the output here.

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.

index.js
Output
Click Run to see the output here.

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:

index.js
Output
Click Run to see the output here.

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:

index.js
Output
Click Run to see the output here.

Lo mismo pasa con los booleanos. !!value funciona y se ve por todos lados, pero Boolean(value) deja claro qué hace:

index.js
Output
Click Run to see the output here.

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.

index.js
Output
Click Run to see the output here.

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:

index.js
Output
Click Run to see the output here.

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:

index.js
Output
Click Run to see the output here.

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("") da 0, Number([]) da 0, Number(null) da 0… pero Number(undefined) da NaN. Estos casos aparecen en bugs reales.
  • Usa Number(x), String(x) y Boolean(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?

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.

Aprende a programar con Coddy

COMENZAR