Introdução: Por que trabalhar com o sistema de arquivos em TypeScript?
\n\nCada aplicação, mais cedo ou mais tarde, enfrenta a necessidade de interagir com o sistema de arquivos: salvar configurações, processar arquivos carregados, manter logs ou gerenciar projetos. TypeScript, sendo uma extensão do JavaScript, fornece ao desenvolvedor ferramentas poderosas para trabalhar com arquivos e diretórios através do módulo fs (File System) do Node.js.
Neste artigo, abordaremos com exemplos práticos as principais operações com o sistema de arquivos em TypeScript: leitura e escrita de arquivos, criação e exclusão de diretórios, além do tratamento de erros. Todos os exemplos serão apresentados com tipagem estrita, que é uma vantagem fundamental do TypeScript.
\n\nMódulos principais para trabalhar com o sistema de arquivos
\n\nAntes de ir para a prática, vamos conhecer os três principais módulos necessários para o trabalho:
\n\n- \n
- fs — módulo principal para operações com o sistema de arquivos (leitura, escrita, exclusão) \n
- fs/promises — versão do módulo
fscom suporte a promises (recomendado para código moderno) \n - path — utilitário para trabalhar com caminhos de arquivos e diretórios \n
Para importar os módulos em TypeScript, use a seguinte sintaxe:
\n\nimport * as fs from 'fs';\nimport * as fsPromises from 'fs/promises';\nimport * as path from 'path';\n\nObservação: para o funcionamento correto com TypeScript, certifique-se de que no seu arquivo tsconfig.json as opções "moduleResolution": "node" e "esModuleInterop": true estejam configuradas.
Leitura de arquivos: abordagens síncrona e assíncrona
\n\nLeitura síncrona com tipagem
\n\nOs métodos síncronos bloqueiam a execução do código até a conclusão da operação. Use-os apenas para arquivos pequenos ou na inicialização da aplicação:
\n\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nfunction readConfigSync(): Record<string, unknown> {\n const configPath = path.join(__dirname, 'config.json');\n \n try {\n const data = fs.readFileSync(configPath, 'utf-8');\n return JSON.parse(data) as Record<string, unknown>;\n } catch (error) {\n if (error instanceof Error) {\n console.error('Erro ao ler configuração:', error.message);\n }\n return {};\n }\n}\n\nconst config = readConfigSync();\nconsole.log('Configuração carregada:', config);\n\nLeitura assíncrona com async/await (método recomendado)
\n\nPara código em produção, sempre use métodos assíncronos. TypeScript funciona muito bem com async/await:
\n\nimport { readFile } from 'fs/promises';\nimport * as path from 'path';\n\ninterface UserData {\n id: number;\n name: string;\n email: string;\n}\n\nasync function readUserData(fileName: string): Promise<UserData[]> {\n const filePath = path.resolve('data', fileName);\n \n try {\n const rawData = await readFile(filePath, { encoding: 'utf-8' });\n const users: UserData[] = JSON.parse(rawData);\n return users;\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Não foi possível ler o arquivo ${fileName}: ${error.message}`);\n }\n throw error;\n }\n}\n\n// Uso\n(async () => {\n try {\n const users = await readUserData('users.json');\n console.log(`Carregados ${users.length} usuários`);\n } catch (error) {\n console.error(error);\n }\n})();\n\nEscrita e atualização de arquivos
\n\nCriação e sobrescrita de arquivos
\n\nPara escrever dados em um arquivo, use o método writeFile. Ele criará o arquivo se não existir ou sobrescreverá o existente:
import { writeFile, mkdir } from 'fs/promises';\nimport * as path from 'path';\n\ninterface LogEntry {\n timestamp: string;\n level: 'info' | 'warn' | 'error';\n message: string;\n}\n\n