Por qué trabajar con archivos en TypeScript no es difícil, sino práctico
\n\nCuando empecé a escribir en TypeScript, me asustaba pensar: «¿Y los archivos? En el navegador todo es fácil, pero aquí hay servidor, discos, rutas...». Pero resultó que trabajar con archivos y el sistema de archivos en TypeScript es como armar un set de LEGO: hay piezas claras (los módulos fs y path), hay instrucciones (tipado), y el resultado es predecible. Sin sorpresas, solo código limpio.
En este artículo, veremos cómo leer, escribir, renombrar y eliminar archivos usando el moderno TypeScript para Node.js. Aprenderá por qué debería usar fs/promises en lugar del antiguo fs, cómo no perderse con las rutas y cómo manejar los errores de forma elegante. ¡Vamos allá!
Preparación: lo que necesita saber antes de empezar
\n\nAntes de sumergirnos en el código, asegúrese de tener Node.js instalado (versión 14+ — ya incluye promesas nativas). También cree un proyecto simple:
\n\nmkdir ts-files-demo\ncd ts-files-demo\nnpm init -y\nnpm install typescript @types/node --save-dev\nnpx tsc --init\n\nEn el archivo tsconfig.json, asegúrese de habilitar "module": "NodeNext" o "ESNext" y "target": "ES2022". Ahora está listo para trabajar con el sistema de archivos en TypeScript.
Importaciones que siempre serán útiles
\n\nLa forma más correcta de importar módulos para trabajar con archivos hoy en día es:
\n\nimport { readFile, writeFile, unlink, mkdir, access } from 'fs/promises';\nimport { join, dirname, basename, extname } from 'path';\nimport { fileURLToPath } from 'url';\n\nTenga en cuenta: no usamos fs con callbacks. Solo fs/promises — es el estándar moderno que combina perfectamente con async/await y el tipado de TypeScript.
Lectura de archivos: de lo simple a lo seguro
\n\nEmpecemos con lo clásico: leer un archivo de texto. Supongamos que tenemos un data.txt con algún contenido.
import { readFile } from 'fs/promises';\n\nasync function readTextFile(filePath: string): Promise<string> {\n try {\n const content = await readFile(filePath, 'utf-8');\n return content;\n } catch (error) {\n console.error('Error al leer el archivo:', error);\n throw error;\n }\n}\n\n// Uso\nconst data = await readTextFile('./data.txt');\nconsole.log(data);\n\nSencillo, ¿verdad? Pero en proyectos reales a menudo trabajamos con JSON. Hagamos una función universal con genéricos:
\n\nimport { readFile } from 'fs/promises';\n\nasync function readJsonFile<T>(filePath: string): Promise<T> {\n const raw = await readFile(filePath, 'utf-8');\n return JSON.parse(raw) as T;\n}\n\n// Ejemplo: leer configuración\ninterface Config {\n port: number;\n dbUrl: string;\n}\n\nconst config = await readJsonFile<Config>('./config.json');\nconsole.log(config.port); // tipo number — TypeScript lo sugiere automáticamente\n\nAsí es el trabajo con archivos en TypeScript en su máxima expresión: el tipado lo protege de errores tontos y el código sigue siendo legible.
\n\nEscritura en archivos: crear y actualizar datos
\n\nAhora aprendamos a guardar información. La función writeFile sobrescribe el archivo si existe, o crea uno nuevo.
import { writeFile, mkdir } from 'fs/promises';\nimport { dirname } from 'path';\n\nasync function saveToFile(filePath: string, data: string): Promise<void> {\n // Primero, asegurémonos de que la carpeta existe\n const dir = dirname(filePath);\n await mkdir(dir, { recursive: true });\n\n // Ahora escribimos\n await writeFile(filePath, data, 'utf-8');\n console.log(`Archivo ${filePath} guardado exitosamente`);\n}\n\n// Guardar un objeto como JSON\nconst user = { name: 'Ana', age: 28, role: 'admin' };\n