Работа с YAML в TypeScript: парсинг, генерация и валидация данных

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

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

Начать курс

Работа с YAML в TypeScript: парсинг, генерация и валидация

YAML (YAML Ain't Markup Language) — один из самых популярных форматов сериализации данных, активно используемый в конфигурационных файлах, DevOps (Docker, Kubernetes, Ansible) и CI/CD пайплайнах. В TypeScript-экосистеме для работы с YAML применяется библиотека js-yaml, которая обеспечивает полную поддержку спецификации YAML 1.2, включая сложные структуры, теги и пользовательские типы данных.

Установка и настройка

Для начала работы установите библиотеку и её типы через npm:

npm install js-yaml
npm install --save-dev @types/js-yaml

После установки вы можете импортировать библиотеку в свой TypeScript-проект:

import * as yaml from 'js-yaml';
import * as fs from 'fs';

Парсинг YAML в TypeScript

Основная функция для чтения YAML — yaml.load(), которая преобразует строку YAML в объект JavaScript/TypeScript. Рассмотрим пример с конфигурационным файлом:

// config.yaml
// server:
//   port: 3000
//   host: "localhost"
// database:
//   url: "mongodb://localhost:27017/mydb"
//   poolSize: 10
// features:
//   - logging
//   - authentication

interface Config {
  server: {
    port: number;
    host: string;
  };
  database: {
    url: string;
    poolSize: number;
  };
  features: string[];
}

const yamlContent = fs.readFileSync('config.yaml', 'utf8');
const config = yaml.load(yamlContent) as Config;

console.log(config.server.port); // 3000
console.log(config.features); // ['logging', 'authentication']

Для безопасного парсинга (без выполнения кода) используйте yaml.load() — он безопаснее, чем yaml.eval(), который может выполнить произвольный JavaScript-код.

Генерация YAML из TypeScript-объектов

Обратная операция — преобразование TypeScript-объекта в строку YAML — выполняется функцией yaml.dump(). Это полезно для создания конфигурационных файлов на лету:

interface DeploymentConfig {
  apiVersion: string;
  kind: string;
  metadata: { name: string; labels?: Record<string, string> };
  spec: { replicas: number; selector: Record<string, string> };
}

const deployment: DeploymentConfig = {
  apiVersion: 'apps/v1',
  kind: 'Deployment',
  metadata: {
    name: 'my-app',
    labels: { app: 'my-app', tier: 'backend' }
  },
  spec: {
    replicas: 3,
    selector: { matchLabels: { app: 'my-app' } }
  }
};

const yamlString = yaml.dump(deployment, {
  indent: 2,
  lineWidth: 120,
  noRefs: true,
  sortKeys: true
});

console.log(yamlString);
// apiVersion: apps/v1
// kind: Deployment
// metadata:
//   labels:
//     app: my-app
//     tier: backend
//   name: my-app
// spec:
//   replicas: 3
//   selector:
//     matchLabels:
//       app: my-app

Работа с пользовательскими типами

Библиотека js-yaml поддерживает пользовательские схемы и типы данных. Это особенно полезно при работе с датами, регулярными выражениями или специальными объектами:

import * as yaml from 'js-yaml';

// Создаем пользовательский тип для дат
const DateType = new yaml.Type('!date', {
  kind: 'scalar',
  resolve: (data: string) => !isNaN(Date.parse(data)),
  construct: (data: string) => new Date(data),
  instanceOf: Date,
  represent: (date: Date) => date.toISOString()
});

// Создаем схему с поддержкой стандартных и пользовательских типов
const schema = yaml.DEFAULT_SCHEMA.extend([DateType]);

const yamlWithDates = `
event: !date 2024-12-25T10:00:00Z
title: "Рождественский семинар"
`;

const parsed = yaml.load(yamlWithDates, { schema });
console.log(parsed.event instanceof Date); // true
console.log(parsed.event.toLocaleDateString('ru-RU')); // 25.12.2024

Валидация YAML с помощью TypeScript

Для обеспечения типобезопасности при работе с YAML-данными рекомендуется использовать библиотеки валидации, такие как zod или io-ts. Пример с zod:

import { z } from 'zod';
import * as yaml from 'js-yaml';

// Определяем схему валидации
const DatabaseConfigSchema = z.object({
  host: z.string().min(1),
  port: z.number().int().positive().max(65535),
  username: z.string().optional(),
  password: z.string().optional(),                    

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