Por que trabalhar com arquivos em TypeScript não é assustador, mas sim conveniente
\n\nQuando comecei a escrever em TypeScript, a ideia me assustava: "E os arquivos? No navegador é simples, mas aqui — servidor, discos, caminhos...". Mas, como se viu, trabalhar com arquivos e sistema de arquivos em TypeScript é como montar um LEGO: há peças claras (módulos fs e path), há instruções (tipagem), e o resultado é previsível. Sem surpresas, apenas código limpo.
Neste artigo, vamos entender como ler, escrever, renomear e excluir arquivos usando o moderno TypeScript para Node.js. Você aprenderá por que usar fs/promises em vez do antigo fs, como não se perder nos caminhos e como tratar erros de forma elegante. Vamos lá!
Preparação: o que você precisa saber antes de começar
\n\nAntes de mergulhar no código, certifique-se de ter o Node.js instalado (versão 14+ — já tem promises nativas). Crie também um projeto simples:
\n\nmkdir ts-files-demo\ncd ts-files-demo\nnpm init -y\nnpm install typescript @types/node --save-dev\nnpx tsc --init\n\nNo arquivo tsconfig.json, certifique-se de ativar "module": "NodeNext" ou "ESNext" e "target": "ES2022". Agora você está pronto para trabalhar com o sistema de arquivos TypeScript.
Importações que sempre serão úteis
\n\nA maneira mais correta de importar módulos para trabalhar com arquivos hoje é:
\n\nimport { readFile, writeFile, unlink, mkdir, access } from 'fs/promises';\nimport { join, dirname, basename, extname } from 'path';\nimport { fileURLToPath } from 'url';\n\nObserve: não usamos fs com callbacks. Apenas fs/promises — este é o padrão moderno, que combina perfeitamente com async/await e a tipagem do TypeScript.
Leitura de arquivo: do simples ao seguro
\n\nVamos começar com o clássico — ler um arquivo de texto. Suponha que temos um data.txt com algum conteúdo.
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('Erro ao ler o arquivo:', error);\n throw error;\n }\n}\n\n// Uso\nconst data = await readTextFile('./data.txt');\nconsole.log(data);\n\nSimples, certo? Mas em projetos reais, frequentemente trabalhamos com JSON. Vamos criar uma função genérica com genérico:
\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// Exemplo: lendo uma configuração\ninterface Config {\n port: number;\n dbUrl: string;\n}\n\nconst config = await readJsonFile<Config>('./config.json');\nconsole.log(config.port); // tipo number — o TypeScript sugere automaticamente\n\nIsso é trabalhar com arquivos TypeScript da melhor forma: a tipagem protege você de erros bobos, e o código permanece legível.
\n\nEscrita em arquivo: criando e atualizando dados
\n\nAgora vamos aprender a salvar informações. A função writeFile sobrescreve o arquivo se ele existir, ou cria um novo.
import { writeFile, mkdir } from 'fs/promises';\nimport { dirname } from 'path';\n\nasync function saveToFile(filePath: string, data: string): Promise<void> {\n // Primeiro, garantimos que a pasta existe\n const dir = dirname(filePath);\n await mkdir(dir, { recursive: true });\n\n // Agora escrevemos\n await writeFile(filePath, data, 'utf-8');\n console.log(`Arquivo ${filePath} salvo com sucesso`);\n}\n\n// Salvando um objeto como JSON\nconst user = { name: 'Ana', age: 28, role: 'admin' };\n