
Como corregir TypeError cannot read property push of undefined en JavaScript
Introduccion al error TypeError en metodos de arrays
El error TypeError cannot read property push of undefined aparece con frecuencia cuando se trabaja con arrays en JavaScript. Este mensaje indica que se intenta invocar un metodo de array sobre un valor que no es un array sino undefined. El mismo tipo de fallo se produce con pop shift unshift o splice. En la practica diaria de desarrollo web este problema suele surgir por una inicializacion incorrecta o por acceder a una propiedad inexistente. Comprender las causas raiz permite escribir codigo mas robusto y evitar interrupciones en tiempo de ejecucion. A lo largo de este articulo se analizan los escenarios mas comunes junto con soluciones concretas y ejemplos actualizados que reflejan el estado actual del lenguaje en 2026.
JavaScript trata los arrays como objetos especiales que disponen de una coleccion de metodos nativos. Cuando la referencia sobre la que se llama el metodo no apunta a un array el motor de JavaScript lanza un TypeError. La frase exacta del mensaje puede variar ligeramente segun el motor pero el nucleo del problema permanece: no se puede leer la propiedad push de un valor undefined. Este comportamiento es coherente con el modelo de tipos dinamicos del lenguaje y con la forma en que se resuelven las propiedades en tiempo de ejecucion.
Los desarrolladores que migran desde lenguajes de tipado estatico a menudo se sorprenden al descubrir que una variable puede permanecer undefined hasta que se le asigna un valor. En JavaScript la declaracion de una variable con let o const no implica automaticamente que se cree un array. Es necesario inicializarla explicitamente. Esta distincion es una de las fuentes principales del error que se estudia aqui.
Ademas del caso basico existen situaciones mas sutiles relacionadas con objetos anidados y con estructuras de datos dinamicas. Por ejemplo cuando se construye un objeto que deberia contener un array como propiedad y esa propiedad nunca se inicializa el intento de usar push genera el mismo TypeError. En entornos de produccion este tipo de fallo puede ser dificil de rastrear si no se cuenta con un manejo adecuado de excepciones o con pruebas unitarias que cubran los caminos de inicializacion.
La evolucion del lenguaje ha introducido herramientas que ayudan a prevenir estos errores. El uso de TypeScript o de comprobaciones estaticas con herramientas modernas permite detectar en tiempo de desarrollo muchas de las situaciones que antes solo se revelaban en ejecucion. No obstante el conocimiento de las causas fundamentales sigue siendo imprescindible para quienes trabajan directamente con JavaScript puro o con frameworks que no imponen tipado estricto.
En las siguientes secciones se examinan uno por uno los escenarios tipicos que provocan el error. Cada escenario incluye ejemplos de codigo que reproducen el problema y la forma correcta de resolverlo. Se incluye tambien una discusion sobre buenas practicas y sobre como estructurar el codigo para minimizar la aparicion de valores undefined en contextos donde se esperan arrays.
Variable previamente asignada a undefined
Una de las formas mas directas de generar el error consiste en asignar explicitamente el valor undefined a una variable y luego intentar llamar a push sobre ella. Aunque pueda parecer un caso artificial ocurre con cierta frecuencia cuando se reutilizan variables o cuando se prepara un valor por defecto que luego se olvida actualizar.
let listaUsuarios = undefined;
listaUsuarios.push("Ana Lopez");
El codigo anterior produce el TypeError porque listaUsuarios no es un array. La solucion consiste en inicializar la variable con un array vacio antes de cualquier operacion de insercion.
let listaUsuarios = [];
listaUsuarios.push("Ana Lopez");
console.log(listaUsuarios);
La salida esperada es un array que contiene el elemento anadido. Esta inicializacion puede realizarse en el momento de la declaracion o en un punto posterior siempre que ocurra antes de la primera llamada al metodo. Cuando se trabaja con variables que pueden recibir valores de distintas fuentes es recomendable realizar una comprobacion previa.
let listaUsuarios;
if (!Array.isArray(listaUsuarios)) {
listaUsuarios = [];
}
listaUsuarios.push("Ana Lopez");
El uso de Array.isArray ofrece una verificacion fiable que distingue arrays de otros tipos de objetos. Esta practica resulta especialmente util en funciones que reciben parametros opcionales y deben garantizar que el valor tratado es siempre un array antes de manipularlo.
En contextos asincronos la asignacion a undefined puede producirse de forma accidental cuando una promesa se rechaza o cuando una peticion de red falla. En esos casos es conveniente establecer un valor por defecto en el manejador de errores para evitar que el flujo posterior intente operar sobre undefined.
El error de inicializacion incorrecta puede detectarse facilmente con herramientas de depuracion modernas. Los navegadores actuales muestran la pila de llamadas completa y resaltan la linea exacta donde se produce el acceso al metodo. Aprovechar esa informacion reduce el tiempo de diagnostico y permite corregir el problema en pocos minutos.
Otra estrategia preventiva consiste en declarar las variables con const siempre que sea posible y asignarles el array en el mismo momento. Si la variable debe reasignarse se utiliza let y se documenta claramente el punto en el que se espera la inicializacion. Estas convenciones de estilo disminuyen la probabilidad de dejar variables en estado undefined de forma involuntaria.
Cuando se trabaja con frameworks de interfaz de usuario la inicializacion de arrays suele realizarse en el estado del componente. Olvidar esa inicializacion produce el mismo TypeError cuando el renderizado o un manejador de eventos intenta actualizar la lista. Revisar el estado inicial de cada componente es por tanto una medida de higiene basica.
Variable declarada pero no inicializada
JavaScript permite declarar una variable sin asignarle valor. En ese caso el valor por defecto es undefined. Intentar llamar a push sobre una variable en ese estado genera el error de forma inmediata.
let carrito;
carrito.push({ id: 1, producto: "Teclado" });
La correccion consiste en inicializar el array en el momento de la declaracion o justo antes de la primera operacion.
let carrito = [];
carrito.push({ id: 1, producto: "Teclado" });
Tambien es valido utilizar el constructor Array aunque la notacion literal es mas concisa y se considera el estilo preferido en la mayoria de bases de codigo modernas.
let carrito = new Array();
carrito.push({ id: 1, producto: "Teclado" });
En funciones que aceptan un parametro opcional de tipo array es habitual encontrar patrones de este tipo. El parametro llega como undefined cuando no se proporciona y el cuerpo de la funcion debe encargarse de la inicializacion.
function agregarProducto(carrito, producto) {
if (carrito === undefined) {
carrito = [];
}
carrito.push(producto);
return carrito;
}
Una version mas compacta utiliza el operador de coalescencia nula disponible desde ES2020.
function agregarProducto(carrito, producto) {
carrito = carrito ?? [];
carrito.push(producto);
return carrito;
}
Este operador solo sustituye el valor cuando es null o undefined lo que lo hace ideal para este escenario. En entornos que deben mantener compatibilidad con versiones anteriores de JavaScript se puede recurrir a una expresion ternaria o a una comprobacion explicita.
La inicializacion tardia de variables tambien puede ocurrir cuando se utilizan declaraciones hoisted con var. Aunque el uso de var ha disminuido considerablemente en codigo nuevo sigue apareciendo en bases de codigo legacy. En esos casos la variable existe pero su valor es undefined hasta la linea de asignacion. Mover la inicializacion al inicio del ambito elimina el riesgo.
Los linters modernos pueden configurarse para advertir sobre variables utilizadas antes de su inicializacion. Activar esas reglas en el flujo de trabajo diario reduce la frecuencia de este tipo de errores. Combinado con pruebas unitarias que cubren los caminos de inicializacion el riesgo de llegar a produccion con un TypeError de este tipo se vuelve minimo.
Cuando se trabaja con modulos ES la inicializacion de variables exportadas debe realizarse en el momento de la declaracion del modulo. Exportar una variable sin inicializar y luego intentar manipularla desde otro modulo produce el mismo problema. Establecer valores por defecto en el punto de exportacion es una practica recomendada.
Llamada al metodo sobre un elemento del array
Los metodos de array deben invocarse sobre el array completo no sobre uno de sus elementos. Intentar llamar a push sobre un indice produce el error porque el elemento individual no posee ese metodo.
let numeros = [10, 20, 30];
numeros[3].push(40);
En este ejemplo numeros[3] evalua a undefined porque el array solo tiene tres elementos. La llamada a push sobre undefined genera el TypeError. La forma correcta de anadir un elemento es invocar el metodo sobre la variable que representa el array.
let numeros = [10, 20, 30];
numeros.push(40);
console.log(numeros);
Si el objetivo es insertar un valor en una posicion concreta se utiliza splice o se asigna directamente al indice deseado.
let numeros = [10, 20, 30];
numeros[3] = 40;
O con splice:
let numeros = [10, 20, 30];
numeros.splice(3, 0, 40);
La confusion entre el array y sus elementos es mas comun de lo que parece especialmente entre desarrolladores que estan aprendiendo la sintaxis de acceso por indice. Una forma de reforzar el concepto es visualizar el array como un objeto cuyas claves son indices numericos y cuyos valores son los elementos. Los metodos viven en el prototipo del array no en cada elemento individual.
Cuando se trabaja con arrays multidimensionales el mismo error puede aparecer si se olvida un nivel de anidamiento. Por ejemplo al intentar hacer push sobre una fila que aun no ha sido creada.
let matriz = [];
matriz[0].push(5);
La solucion pasa por inicializar primero la fila.
let matriz = [];
matriz[0] = [];
matriz[0].push(5);
O de forma mas segura:
let matriz = [];
if (!Array.isArray(matriz[0])) {
matriz[0] = [];
}
matriz[0].push(5);
Estas comprobaciones se vuelven criticas en algoritmos que construyen estructuras de datos de forma dinamica. Incluirlas desde el principio evita horas de depuracion posterior.
En el contexto de librerias de visualizacion de datos o de graficos es habitual manipular series de valores que se representan como arrays. Un fallo de inicializacion en una de las series puede provocar el TypeError en el momento de anadir un nuevo punto de datos. Validar la estructura antes de cada operacion de escritura es una defensa efectiva.
Propiedad de objeto inexistente o con valor undefined
El ultimo escenario frecuente involucra objetos cuyas propiedades se espera que contengan arrays. Si la propiedad no existe o se ha inicializado con undefined el intento de llamar a push produce el error.
const usuario = { nombre: "Carlos" };
usuario.puntuaciones.push(95);
En este caso la propiedad puntuaciones no existe por lo que su valor es undefined. La correccion consiste en inicializar la propiedad con un array vacio.
const usuario = { nombre: "Carlos", puntuaciones: [] };
usuario.puntuaciones.push(95);
Cuando el objeto se construye de forma dinamica o se recibe de una API externa es necesario comprobar la existencia de la propiedad antes de usarla.
const usuario = { nombre: "Carlos" };
if (!Array.isArray(usuario.puntuaciones)) {
usuario.puntuaciones = [];
}
usuario.puntuaciones.push(95);
El operador de encadenamiento opcional combinado con una asignacion puede simplificar el patron en entornos modernos.
const usuario = { nombre: "Carlos" };
usuario.puntuaciones = usuario.puntuaciones ?? [];
usuario.puntuaciones.push(95);
Esta tecnica es especialmente util cuando se trabaja con objetos anidados de varios niveles. En lugar de escribir comprobaciones largas se puede garantizar la existencia de cada nivel antes de operar.
En aplicaciones que gestionan estado global o que utilizan patrones de store la inicializacion de propiedades array suele realizarse en el estado inicial del store. Olvidar esa inicializacion provoca el TypeError cuando un reducer o una accion intenta actualizar la lista. Revisar el estado inicial y los reducers con pruebas unitarias es la forma mas efectiva de prevenir el problema.
Cuando se deserializan datos JSON es posible que una propiedad esperada como array llegue como null o como un tipo diferente. Realizar una normalizacion inmediata despues de la deserializacion convierte esos valores en arrays vacios y evita errores posteriores.
function normalizarUsuario(datos) {
return {
nombre: datos.nombre ?? "",
puntuaciones: Array.isArray(datos.puntuaciones)
? datos.puntuaciones
: [],
};
}
Esta funcion de normalizacion puede aplicarse a cada objeto recibido de una fuente externa garantizando que las operaciones posteriores siempre encuentren arrays validos.
El manejo seguro de propiedades se ha vuelto mas sencillo con las caracteristicas introducidas en las ultimas versiones del lenguaje. Sin embargo la responsabilidad de inicializar correctamente sigue recayendo en el desarrollador. Documentar las expectativas de cada propiedad y validarlas en los limites del sistema reduce la superficie de error.
Buenas practicas para prevenir el error
Mas alla de corregir los casos individuales existen practicas sistematicas que disminuyen la probabilidad de encontrar el TypeError en el futuro. La primera consiste en inicializar siempre los arrays en el momento de la declaracion cuando se conoce de antemano que se necesitaran.
const historial = [];
const etiquetas = [];
const mensajes = [];
Cuando la inicializacion depende de datos externos se utiliza una funcion de fabrica o un valor por defecto.
function crearLista(datos = []) {
return Array.isArray(datos) ? [...datos] : [];
}
El uso de TypeScript o de JSDoc con comprobaciones de tipo permite detectar muchos de estos problemas antes de la ejecucion. Declarar una propiedad como number[] o Array
En entornos de prueba se recomienda incluir casos que cubran la ausencia de la propiedad o el valor undefined. Un test que espere un TypeError puede servir como documentacion viva del comportamiento esperado y como regresion futura.
Las herramientas de analisis estatico como ESLint pueden configurarse con reglas que advierten sobre el uso de metodos de array sobre variables potencialmente undefined. Activar esas reglas en el pipeline de integracion continua evita que el codigo problemático llegue a las ramas principales.
Cuando se trabaja con codigo asincrono es util envolver las operaciones de mutacion de arrays en bloques try catch que registren el contexto completo del error. Aunque el objetivo es prevenir el error en primer lugar un buen manejo de excepciones facilita el diagnostico cuando el problema aparece en produccion.
La validacion temprana de datos constituye otra defensa importante. En lugar de asumir que un valor es un array se verifica en el punto de entrada de la funcion o del modulo. Esta practica es especialmente valiosa en aplicaciones que procesan datos de usuarios o de servicios de terceros.
En frameworks de componentes la inicializacion de arrays en el estado se realiza normalmente en el constructor o en la funcion de inicializacion del estado. Establecer valores por defecto alli y evitar mutaciones directas del estado ayuda a mantener la consistencia.
Finalmente el uso de metodos inmutables como concat o el operador de propagacion puede reducir la necesidad de mutar arrays existentes y por tanto la exposicion a este tipo de errores. Aunque no elimina por completo el problema ofrece un estilo de programacion que tiende a ser mas predecible.
Consideraciones adicionales en entornos modernos
En 2026 el ecosistema JavaScript incluye caracteristicas que facilitan la prevencion de errores relacionados con undefined. El operador de coalescencia nula el encadenamiento opcional y las aserciones de tipo en TypeScript son herramientas cotidianas. Sin embargo ninguna de ellas sustituye el conocimiento de los fundamentos del lenguaje.
Cuando se utiliza React Vue o Svelte la inicializacion de arrays en el estado del componente sigue las mismas reglas que en JavaScript puro. Un estado inicial incompleto produce el TypeError en el momento de actualizar la lista. Las herramientas de desarrollo de cada framework suelen resaltar la linea exacta donde se produce el acceso ilegal lo que acelera el diagnostico.
En el servidor con Node.js el mismo error puede aparecer al procesar datos de bases de datos o de colas de mensajes. Normalizar los datos en la capa de acceso a datos evita que los errores se propaguen a la logica de negocio.
Las pruebas de contrato y las esquemas de validacion con bibliotecas como Zod o Yup permiten definir de forma declarativa que una propiedad debe ser un array. Al validar los datos en los limites del sistema se reduce drasticamente la probabilidad de encontrar valores undefined en el interior de la aplicacion.
El control de flujo asincrono introduce oportunidades adicionales para que aparezcan valores undefined. Una promesa que se resuelve con un objeto incompleto o un generador que no produce el valor esperado puede dejar una variable en estado undefined. Utilizar async await con comprobaciones explicitas despues de cada await mantiene el control sobre el estado de los datos.
En aplicaciones de gran escala la adopcion de arquitecturas de dominios o de patrones de diseno orientados a objetos permite encapsular la inicializacion de arrays dentro de constructores o de metodos de fabrica. De esta forma el resto del codigo puede asumir que las propiedades siempre estan listas para ser utilizadas.
La documentacion interna del equipo debe incluir ejemplos claros de como inicializar arrays y de como manejar propiedades opcionales. Un estilo de codigo consistente reduce la carga cognitiva y disminuye la frecuencia de errores de este tipo.
Ejemplos integrados y patrones reutilizables
A continuacion se presentan patrones reutilizables que pueden aplicarse en distintos contextos. El primero es una funcion utilitaria que garantiza que un valor es un array.
function asegurarArray(valor) {
if (Array.isArray(valor)) {
return valor;
}
if (valor === null || valor === undefined) {
return [];
}
return [valor];
}
Esta funcion puede usarse en cualquier punto donde se reciba un valor potencialmente problematico.
let datos = asegurarArray(respuestaApi.items);
datos.push(nuevoItem);
Otro patron util es la inicializacion segura de propiedades anidadas.
function asegurarPropiedadArray(objeto, ruta) {
const partes = ruta.split(".");
let actual = objeto;
for (let i = 0; i < partes.length - 1; i++) {
const clave = partes[i];
if (!actual[clave] || typeof actual[clave] !== "object") {
actual[clave] = {};
}
actual = actual[clave];
}
const ultima = partes[partes.length - 1];
if (!Array.isArray(actual[ultima])) {
actual[ultima] = [];
}
return actual[ultima];
}
Uso:
const usuario = {};
const puntuaciones = asegurarPropiedadArray(usuario, "perfil.puntuaciones");
puntuaciones.push(100);
Estos patrones pueden extraerse a un modulo de utilidades compartido y reutilizarse en toda la base de codigo. Con el tiempo se convierten en parte del vocabulario del equipo y reducen la aparicion de errores similares.
Cuando se trabaja con inmutabilidad es preferible crear un nuevo array en lugar de mutar el existente. El operador de propagacion facilita esta operacion.
const listaActualizada = [...listaOriginal, nuevoElemento];
Si se necesita mutar el array original se debe garantizar previamente que no es undefined.
if (Array.isArray(listaOriginal)) {
listaOriginal.push(nuevoElemento);
}
La combinacion de comprobaciones explicitas y de estilos inmutables ofrece un equilibrio entre seguridad y claridad.
Conclusiones
El error TypeError cannot read property push of undefined es una consecuencia directa de intentar operar sobre un valor que no es un array. Las causas mas comunes son la asignacion previa a undefined la falta de inicializacion el acceso a un elemento en lugar del array completo y la ausencia de una propiedad de objeto. Cada una de estas situaciones tiene una solucion sencilla basada en la inicializacion correcta del array.
Adoptar practicas de inicializacion temprana de comprobacion con Array.isArray y de normalizacion de datos en los limites del sistema elimina la mayoria de las ocurrencias del error. Las herramientas modernas de tipado y de analisis estatico refuerzan estas practicas y permiten detectar problemas antes de la ejecucion.
El conocimiento de los fundamentos del modelo de tipos de JavaScript sigue siendo la base para escribir codigo robusto. Aunque el lenguaje ha evolucionado con nuevas sintaxis y operadores el principio de no invocar metodos de array sobre valores undefined permanece invariable. Aplicar de forma consistente las tecnicas presentadas en este articulo permite construir aplicaciones mas estables y reducir el tiempo dedicado a la depuracion de errores de este tipo.