Introdução: por que é necessário trabalhar com o sistema de arquivos em TypeScript
TypeScript, sendo uma extensão estritamente tipada sobre JavaScript, oferece aos desenvolvedores ferramentas poderosas para trabalhar com o sistema de arquivos. Independentemente de você estar criando um utilitário para processar logs, um servidor web com upload de arquivos ou uma ferramenta para migração de dados — saber interagir eficientemente com o sistema de arquivos é uma habilidade básica.
Neste artigo, exploraremos os aspectos práticos de trabalhar com o sistema de arquivos em TypeScript usando o módulo embutido fs (File System) do Node.js. Todos os exemplos serão acompanhados de comentários e explicações detalhadas. Abordaremos métodos síncronos e assíncronos, trabalho com caminhos e tipagem de dados.
1. Configuração do projeto e importação do módulo fs
Antes de começar, é necessário configurar um projeto TypeScript. Certifique-se de ter o Node.js e o gerenciador de pacotes npm instalados. Crie um novo projeto e instale os tipos para Node.js:
npm init -ynpm install typescript @types/node --save-devnpm install ts-node --save-devCrie um arquivo tsconfig.json e adicione as configurações básicas:
{ "compilerOptions": { "target": "ES2020", "module": "commonjs", "strict": true, "esModuleInterop": true, "outDir": "./dist", "rootDir": "./src" }, "include": ["src/**/*"]}Agora, no seu arquivo index.ts, importe os módulos fs e path:
import * as fs from 'fs';import * as path from 'path';Importante: Em TypeScript, usamos import * as para importar todo o módulo. Isso garante a tipagem completa de todos os métodos.
2. Leitura de arquivos: abordagens síncrona e assíncrona
2.1 Leitura assíncrona (método recomendado)
Em TypeScript, é preferível usar métodos assíncronos, pois eles não bloqueiam o fluxo principal de execução. Vejamos um exemplo de leitura de um arquivo de texto:
import * as fs from 'fs/promises';import * as path from 'path';
async function readFileExample(filePath: string): Promise<string> { try { const absolutePath = path.resolve(filePath); const content: string = await fs.readFile(absolutePath, 'utf-8'); return content; } catch (error) { if (error instanceof Error) { throw new Error(`Erro ao ler o arquivo: ${error.message}`); } throw error; }}
// Uso(async () => { const data = await readFileExample('./data/example.txt'); console.log('Conteúdo do arquivo:', data);})();Observe o uso de fs/promises — esta é a versão do módulo com promises, que se integra perfeitamente com async/await em TypeScript.
2.2 Leitura síncrona (para cenários simples)
Às vezes, por exemplo, ao carregar uma configuração na inicialização, você pode usar métodos síncronos:
import * as fs from 'fs';import * as path from 'path';
function readConfigSync(configPath: string): Record<string, unknown> { const fullPath = path.join(__dirname, configPath); const rawData = fs.readFileSync(fullPath, 'utf-8'); return JSON.parse(rawData);}
const config = readConfigSync('./config.json');console.log('Configuração:', config);3. Escrita e modificação de arquivos
3.1 Escrevendo dados em um arquivo
Para escrever dados em um arquivo, use writeFile. TypeScript permite tipar estritamente os dados antes da escrita:
import * as fs from 'fs/promises';
interface UserData { id: number; name: string; email: string;}
async function saveUserData(users: UserData[]): Promise<void> { const jsonString: string = JSON.stringify(users, null, 2); await fs.writeFile('./users.json', jsonString, 'utf-8'); con