Array<Type> vs Type[] en TypeScript: la batalla de sintaxis que debe ganar
\n\nSi alguna vez ha escrito en TypeScript, seguramente ha visto dos formas de declarar un array de números:
\n\nconst numbers1: number[] = [1, 2, 3];\nconst numbers2: Array<number> = [1, 2, 3];\n\nAmbas opciones funcionan. Ambas se compilan. Ambas son TypeScript válido. Entonces, ¿por qué hay tanto debate al respecto? ¿Por qué esta pregunta en Stack Overflow ha acumulado miles de visitas? Y lo más importante: ¿cómo evitar los errores que pueden arruinar su proyecto?
\n\nAclaremos esto de una vez por todas. Sin teoría aburrida. Solo lo que realmente será útil en la práctica.
\n\nBreve introducción: qué es qué
\n\nSintaxis Type[] (Array Literal Syntax)
\n\nEsta es la forma más común de declarar un array en TypeScript. Proviene de JavaScript y se ve natural:
\n\nlet fruits: string[] = ['apple', 'banana', 'cherry'];\nlet matrix: number[][] = [[1, 2], [3, 4]]; // Array de arrays\n\nCorto, legible, intuitivo. Para el 90% de los casos, esto es suficiente.
\n\nSintaxis Array<Type> (Generic Syntax)
\n\nEsta es la forma genérica, que utiliza la interfaz incorporada Array<T>:
let fruits: Array<string> = ['apple', 'banana', 'cherry'];\nlet matrix: Array<Array<number>> = [[1, 2], [3, 4]];\n\nSe ve más "académica", pero ofrece mayor flexibilidad en escenarios complejos.
\n\nTop 5 errores que cometen incluso los desarrolladores experimentados
\n\nError n.º 1: Confianza ciega en el autocompletado del IDE
\n\nSu IDE puede sugerir ambas opciones. Pero eso no significa que sean intercambiables en todas partes. Veamos un ejemplo con tipos unión:
\n\n// Así sí se puede\ntype Status = 'active' | 'inactive';\nconst statuses1: Status[] = ['active', 'inactive'];\n\n// Pero así — ¡error de sintaxis!\n// const statuses2: Array<'active' | 'inactive'> = ['active', 'inactive']; \n// ❌ Error: se esperaba ';'\n\n// Opción correcta con genérico:\nconst statuses3: Array<Status> = ['active', 'inactive'];\n\nConclusión: Dentro de Array<> no se pueden usar tipos unión complejos directamente. Primero, extráigalos a un tipo separado.
Error n.º 2: Confusión con arrays de solo lectura
\n\nCuando necesita hacer un array inmutable, las sintaxis se comportan de manera diferente:
\n\n// ✅ Correcto con Type[]\nconst readonlyFruits: readonly string[] = ['apple', 'banana'];\n// readonlyFruits.push('orange'); // ❌ Error: readonly\n\n// ❌ Así no funciona:\n// const wrong: readonly Array<string> = ['apple']; \n// Error: el modificador 'readonly' solo puede aparecer en tipos de array\n\n// ✅ Correcto con Array<> — use ReadonlyArray:\nconst correct: ReadonlyArray<string> = ['apple', 'banana'];\n\nConclusión: Para arrays de solo lectura, use readonly Type[] o ReadonlyArray<Type>. No se puede mezclar readonly con Array<>.
Error n.º 3: Problemas con arrays multinivel
\n\nCuando un array contiene otros arrays, la sintaxis Array<> se vuelve engorrosa:
// Legible y claro\nconst grid1: number[][] = [[1, 2], [3, 4]];\n\n// Ya es más difícil de leer\nconst grid2: Array<Array<number>> = [[1, 2], [3, 4]];\n\n// ¿Y si son tres niveles? Una pesadilla:\nconst cube: Array<Array<Array<number>>> = [[[1]]]; // 🤯\n\n// Con Type[] es más sencillo:\nconst cube2: number[][][] = [[[1]]];\n\nConclusión: Para arrays con más de 2 niveles de anidamiento, use Type[][]. Sus colegas se lo agradecerán.
Error n.º 4: Ignorar el contexto de uso
\n\nEn algunos frameworks (Angular, React) y bibliotecas, se adopta un estilo determinado. Violar la convención puede causar confusión:
\n\n// Angular a menudo u