Работа с файловой системой в TypeScript для начинающих

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение в работу с файловой системой в TypeScript

Работа с файловой системой — одна из ключевых задач при разработке на TypeScript. Независимо от того, создаёте ли вы серверное приложение, утилиту для обработки данных или веб-сервер, вам обязательно понадобится читать, записывать и управлять файлами и директориями. В этом руководстве мы разберём основы работы с модулем fs (File System) в TypeScript, рассмотрим синхронные и асинхронные операции, а также научимся обрабатывать ошибки.

TypeScript — это строго типизированная надстройка над JavaScript, которая добавляет статическую типизацию. При работе с файловой системой мы будем использовать стандартный модуль Node.js fs, но с дополнительными преимуществами TypeScript: автодополнением, проверкой типов и улучшенной читаемостью кода.

Настройка проекта и импорт модулей

Прежде чем начать, убедитесь, что у вас установлен Node.js и TypeScript. Создайте новый проект и установите необходимые типы:

mkdir fs-typescript-tutorial
cd fs-typescript-tutorial
npm init -y
npm install typescript @types/node --save-dev
npx tsc --init

Для работы с файловой системой нам понадобятся два основных модуля:

  • fs — для выполнения операций с файлами (чтение, запись, удаление и т.д.)
  • path — для удобной работы с путями (объединение, нормализация, получение расширения)

Импортируем их в наш TypeScript-файл:

import * as fs from 'fs';
import * as path from 'path';

// Альтернативный вариант — импорт только нужных функций:
import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';
import { join, resolve } from 'path';

Обратите внимание: мы используем import * as fs, так как модуль fs экспортирует множество функций. TypeScript автоматически подхватит типы из установленного пакета @types/node.

Чтение и запись файлов

Начнём с самых базовых операций — чтения и записи текстовых файлов. В Node.js есть два подхода: синхронный и асинхронный. Для простых скриптов и утилит часто используют синхронные методы, а для высоконагруженных серверов — асинхронные, чтобы не блокировать event loop.

Синхронное чтение и запись

Синхронные методы блокируют выполнение программы до завершения операции. Они просты в использовании и подходят для сценариев, где скорость не критична:

import { readFileSync, writeFileSync } from 'fs';
import { join } from 'path';

const filePath = join(__dirname, 'data.txt');

// Запись в файл (создаёт файл, если его нет)
writeFileSync(filePath, 'Hello, TypeScript!', 'utf-8');

// Чтение из файла
const content: string = readFileSync(filePath, 'utf-8');
console.log(content); // Выведет: Hello, TypeScript!

Обратите внимание на типизацию content: string — TypeScript гарантирует, что мы получим строку. Если файл не существует, будет выброшено исключение, которое нужно обработать через try/catch.

Асинхронное чтение и запись

Асинхронные методы принимают колбэк или возвращают Promise (в современных версиях). Рекомендуется использовать Promise-версии с async/await:

import { promises as fsPromises } from 'fs';
import { join } from 'path';

const filePath = join(__dirname, 'async-data.txt');

async function handleFile(): Promise<void> {
    try {
        // Асинхронная запись
        await fsPromises.writeFile(filePath, 'Async content', 'utf-8');
        
        // Асинхронное чтение
        const data: string = await fsPromises.readFile(filePath, 'utf-8');
        console.log(data); // Async content
    } catch (error) {
        console.error('Ошибка при работе с файлом:', error);
    }
}

handleFile();

Использование async/await делает код похожим на синхронный, но при этом не блокирует выполнение. Тип Promise<void> явно указывает, что функция возвращает промис.

Работа с директориями и проверка существования

Часто нужно не только читать файлы, но и управлять папками: создавать, удалять, проверять их наличие. Рассмотрим основные операции.

Создание директорий

Для создания одной папки используем mkdir, а для вложенных структур — опцию recursive: true:

import { mkdirSync, existsSync } from 'fs';
import { join } from 'path';

const dirPath = join(__dirname, 'my-folder', 'sub-folder');

// Проверяем, существует ли директория
if (!existsSync(dirPath)) {
    // Создаём вложенную структуру папок
    mkdirSync(dirPath, { recursive: true });
    console.log('Директория создана');
} else {
    console.log('Директория уже существует');
}

Асинхронный вариант:

import { promises as fsPromises } from 'fs';

async function createDir(): Promise<void> {
    await fsPromises.mkdir(dirPath, { recursive: true });
}

Чтение содержимого директории

Чтобы получить список файлов и папок внутри директории, используем readdir:

import { readdirSync } from 'fs';

const items: string[] = readdirSync(__dirname);
console.log('Содержимое текущей папки:', items);
// Выведет: ['data.txt', 'my-folder', 'index.ts', ...]

TypeScript автоматически выводит тип string[] для массива имён. Если нужно получить полную информацию о каждом элементе (размер, дата создания), используйте readdirSync с опцией { withFileTypes: true } — тогда вы получите массив объектов Dirent.

Проверка типа файла

Часто требуется узнать, является ли элемент файлом или папкой. Для этого используем stat:

import { statSync } from 'fs';

const targetPath = join(__dirname, 'my-folder');
const stats = statSync(targetPath);

if (stats.isFile()) {
    console.log('Это файл');
} else if (stats.isDirectory()) {
    console.log('Это папка');
}

console.log('Размер:', stats.size, 'байт');
console.log('Дата создания:', stats.birthtime);

Блоги

Рекомендаций по книгам