Работа с CSV в TypeScript: полное руководство
CSV (Comma-Separated Values) — один из самых популярных форматов для обмена табличными данными. В TypeScript (и JavaScript) существует несколько мощных библиотек для парсинга, генерации и обработки CSV-файлов. В этой статье мы рассмотрим основные инструменты, их возможности и приведём практические примеры.
Зачем использовать библиотеки для CSV?
Встроенные средства JavaScript (например, split(',')) не учитывают сложные случаи:
- Экранированные кавычки и запятые внутри полей
- Разные разделители (точка с запятой, табуляция)
- Разные кодировки и BOM
- Многострочные значения
- Разные типы окончания строк (CRLF, LF)
Профессиональные библиотеки решают все эти проблемы и предоставляют удобный API для работы с данными.
1. csv-parse — парсинг CSV в Node.js и браузере
csv-parse — это часть экосистемы csv.js, одна из самых популярных библиотек для парсинга. Она работает как в Node.js, так и в браузере (через bundler).
Установка
npm install csv-parse
Пример использования с TypeScript
import { parse } from 'csv-parse/sync';
import { readFileSync } from 'fs';
interface User {
id: number;
name: string;
email: string;
}
const csvData = readFileSync('users.csv', 'utf-8');
const records: User[] = parse(csvData, {
columns: true, // первая строка — заголовки
skip_empty_lines: true,
delimiter: ',',
cast: (value, context) => {
if (context.column === 'id') return parseInt(value, 10);
return value;
}
});
console.log(records);
2. PapaParse — универсальный парсер для браузера и Node.js
PapaParse — это библиотека с отличной поддержкой больших файлов (потоковая обработка), автоматическим определением разделителя и широкими возможностями конфигурации.
Установка
npm install papaparse
Пример с типизацией результатов
import Papa from 'papaparse';
interface Product {
sku: string;
price: number;
quantity: number;
}
const csvString = `sku,price,quantity
ABC-001,29.99,100
ABC-002,49.50,50`;
const result = Papa.parse<Product>(csvString, {
header: true,
dynamicTyping: true, // автоматическое преобразование типов
skipEmptyLines: true
});
if (result.errors.length > 0) {
console.error('Ошибки парсинга:', result.errors);
} else {
result.data.forEach(product => {
console.log(`Товар ${product.sku}: ${product.price} руб.`);
});
}
3. csv-stringify — генерация CSV из данных
Для обратной задачи — создания CSV из массивов объектов — используйте csv-stringify. Он также входит в экосистему csv.js.
Установка
npm install csv-stringify
Пример генерации CSV
import { stringify } from 'csv-stringify/sync';
import { writeFileSync } from 'fs';
interface Order {
orderId: number;
customer: string;
total: number;
}
const orders: Order[] = [
{ orderId: 1001, customer: 'Иван Петров', total: 1500.50 },
{ orderId: 1002, customer: 'Мария Сидорова', total: 2300.00 },
{ orderId: 1003, customer: 'Алексей Иванов', total: 890.75 }
];
const csvOutput = stringify(orders, {
header: true,
columns: ['orderId', 'customer', 'total']
});
writeFileSync('orders.csv', csvOutput, 'utf-8');
console.log('CSV файл создан успешно');
4. Обработка ошибок и валидация данных
При работе с CSV важно корректно обрабатывать ошибки. Рассмотрим пример с проверкой данных:
import Papa from 'papaparse';
interface ValidatedRow {
isValid: boolean;
errors: string[];
data: Record<string, any>;
}
function validateCSV(csvString: string): ValidatedRow[] {
const result = Papa.parse(csvString, { header: true, skipEmptyLines: true });
return result.data.map((row: any) => {
const errors: string[] = [];
if (!row.email || !row.email.includes('@')) {
errors.push('Некорректный email');
}
if (!row.age || isNaN(Number(row.age)) || Number(row.age) < 0) {
errors.push('Некорректный возраст');
}
return {
isValid: errors.length === 0,
errors,
data: row
};
});
}
// Использование
const csvSample = `name,