Типизация API при использовании TypeScript

Типизация API при использовании TypeScript

TypeScript-интеграция с Rollup позволяет не только получать строгую типизацию конфигурации сборки, но и безопасно описывать плагины, хуки и возвращаемые структуры, что особенно важно при построении сложных сборочных пайплайнов. В контексте Rollup типизация охватывает несколько уровней: входные и выходные опции, плагины, результаты сборки, а также внутренние структуры модулей и графа зависимостей.

Основной пакет типов поставляется вместе с Rollup и экспортируется напрямую из основного модуля. Это означает, что дополнительная установка @types/rollup не требуется. Все ключевые интерфейсы доступны через импорт из rollup.


Конфигурация Rollup строится вокруг двух ключевых интерфейсов: InputOptions и OutputOptions. Они формируют основу типизации всей сборочной системы.

import type { InputOptions, OutputOptions } from 'rollup';

InputOptions

InputOptions описывает входную точку сборки и поведение компиляции.

Ключевые поля:

  • input: string | string[] | Record<string, string>
  • plugins?: Plugin[]
  • external?: ExternalOption
  • onwarn?: (warning, warn) => void
  • preserveEntrySignatures?: boolean | 'strict' | 'allow-extension'

Типизация входных опций позволяет строго контролировать структуру проекта, особенно при использовании нескольких entry-point’ов.

Пример строгой типизации конфигурации:

import type { InputOptions } from 'rollup';

const inputOptions: InputOptions = {
  input: {
    main: 'src/main.ts',
    admin: 'src/admin.ts'
  },
  plugins: []
};

Ошибки типов здесь выявляются на этапе компиляции: например, попытка передать объект неправильной структуры в input будет немедленно зафиксирована TypeScript.


OutputOptions

OutputOptions описывает параметры генерации бандла.

import type { OutputOptions } from 'rollup';

Основные поля:

  • dir?: string
  • file?: string
  • format: 'esm' | 'cjs' | 'iife' | 'umd' | 'system'
  • sourcemap?: boolean | 'inline' | 'hidden'
  • name?: string
  • globals?: Record<string, string>

Типизация форматов вывода позволяет ограничить возможные значения и исключить ошибки конфигурации, связанные с неправильными строковыми литералами.

const outputOptions: OutputOptions = {
  file: 'dist/bundle.js',
  format: 'esm',
  sourcemap: true
};

Тип Bundle и генерация результата

После вызова rollup.rollup() возвращается объект типа RollupBuild, который содержит методы генерации и записи бандла.

import type { RollupBuild } from 'rollup';

Ключевые методы:

  • generate(options: OutputOptions): Promise<RollupOutput>
  • write(options: OutputOptions): Promise<RollupOutput>
  • close(): Promise<void>

Тип RollupOutput описывает результат сборки и включает массив output, содержащий chunks и assets.

import { rollup } from 'rollup';
import type { RollupBuild } from 'rollup';

async function build(): Promise<RollupBuild> {
  const bundle = await rollup({
    input: 'src/index.ts'
  });

  return bundle;
}

Типизация результата позволяет безопасно работать с итоговыми чанками:

const result = await bundle.generate(outputOptions);

result.output.forEach((chunkOrAsset) => {
  if (chunkOrAsset.type === 'chunk') {
    // строго типизированный chunk
    console.log(chunkOrAsset.code);
  } else {
    // asset
    console.log(chunkOrAsset.fileName);
  }
});

Типизация плагинов

Плагины являются одним из наиболее сложных объектов с точки зрения типизации, поскольку они представляют собой набор необязательных хуков.

Базовый интерфейс:

import type { Plugin } from 'rollup';

Минимальная структура плагина:

const myPlugin: Plugin = {
  name: 'my-plugin'
};

Каждый хук имеет собственную сигнатуру. Например:

resolveId

resolveId?: (
  source: string,
  importer: string | undefined
) => string | null | void;

load

load?: (id: string) => string | null | void;

transform

transform?: (
  code: string,
  id: string
) => string | void | { code: string; map?: any };

TypeScript позволяет строго контролировать возвращаемые значения, что особенно важно при работе с sourcemap-структурами.


Типизация transform-результатов

Хук transform поддерживает несколько форм возвращаемых значений:

  • строка кода
  • объект { code, map }
  • null или undefined

Пример строгой типизации:

import type { TransformResult } from 'rollup';

function transform(
  code: string
): TransformResult {
  return {
    code: code.replace('var', 'const'),
    map: null
  };
}

Тип TransformResult гарантирует соответствие структуры ожиданиям Rollup.


Типизация sourcemap

Rollup использует совместимую со стандартом структуру source map. В TypeScript она представлена типом SourceMapInput и SourceMapOutput.

import type { SourceMapInput } from 'rollup';

Пример использования:

const map: SourceMapInput = {
  version: 3,
  mappings: '',
  sources: ['input.ts'],
  names: []
};

Типизация предотвращает ошибки, связанные с отсутствием обязательных полей (version, mappings, sources).


Тип ExternalOption

Поле external поддерживает несколько форм:

import type { ExternalOption } from 'rollup';

Возможные варианты:

  • string[]
  • (id: string, parentId: string, isResolved: boolean) => boolean
  • RegExp

Пример функции:

const external: ExternalOption = (id) => {
  return id.startsWith('node:');
};

TypeScript проверяет корректность сигнатуры и возвращаемого значения, предотвращая ошибки логики исключения зависимостей.


Типизация watcher API

Rollup предоставляет API наблюдения за изменениями файлов через rollup.watch.

import type { Watcher, RollupWatchOptions } from 'rollup';

Тип Watcher содержит события:

  • event: 'START' | 'BUNDLE_START' | 'BUNDLE_END' | 'END' | 'ERROR'
  • методы управления процессом: close(), on()

Пример типизации:

const watcher: Watcher = watch({
  input: 'src/index.ts'
});

watcher.on('event', (event) => {
  if (event.code === 'BUNDLE_END') {
    console.log(event.duration);
  }
});

TypeScript позволяет строго различать типы событий через discriminated unions, что делает обработку событий безопасной и предсказуемой.


Типизация глобальных интерфейсов бандла

Объект чанка в Rollup имеет тип OutputChunk.

import type { OutputChunk } from 'rollup';

Основные поля:

  • code: string
  • fileName: string
  • imports: string[]
  • modules: Record<string, ModuleInfo>

Тип ModuleInfo содержит информацию о каждом модуле:

import type { ModuleInfo } from 'rollup';
  • id: string
  • code?: string
  • originalLength: number
  • renderedLength: number

Типизация модулей особенно полезна при анализе графа зависимостей и построении собственных плагинов анализа бандла.


Расширение типов через декларации

Rollup позволяет расширять типы плагинов через module augmentation.

declare module 'rollup' {
  interface Plugin {
    myCustomField?: boolean;
  }
}

Это используется для:

  • добавления метаданных плагина
  • расширения внутренней конфигурации
  • интеграции сторонних инструментов

TypeScript корректно объединяет расширенные интерфейсы с базовыми типами Rollup.


Типизация контекста плагина

Контекст, передаваемый в хуки, имеет тип PluginContext.

import type { PluginContext } from 'rollup';

Основные методы:

  • emitFile
  • resolve
  • parse

Пример использования:

function transform(this: PluginContext, code: string) {
  const id = this.emitFile({
    type: 'asset',
    name: 'example.txt',
    source: code
  });

  return code;
}

Типизация this в хуках позволяет использовать контекст без потери IntelliSense и проверки типов.


Строгая типизация через generics

Некоторые API Rollup используют generics для повышения точности типов.

Пример:

import type { Plugin } from 'rollup';

interface MyPluginOptions {
  prefix: string;
}

function myPlugin(options: MyPluginOptions): Plugin {
  return {
    name: 'my-plugin',
    transform(code) {
      return options.prefix + code;
    }
  };
}

Хотя Rollup не требует generics напрямую, TypeScript позволяет оборачивать плагины в строго типизированные фабрики, что повышает предсказуемость поведения.


Типизация ошибок сборки

Ошибки Rollup представлены типом RollupError.

import type { RollupError } from 'rollup';

Основные поля:

  • message: string
  • code?: string
  • id?: string
  • stack?: string

Используется в onwarn и обработчиках watcher:

onwarn(warning: RollupError) {
  if (warning.code === 'UNRESOLVED_IMPORT') {
    return;
  }
}

Строгая типизация предупреждений позволяет централизованно управлять поведением сборки.


Типизация асинхронных хуков

Многие плагины используют асинхронные хуки:

transform?: (
  code: string,
  id: string
) => Promise<TransformResult> | TransformResult;

TypeScript объединяет синхронные и асинхронные варианты через union типов, обеспечивая гибкость без потери строгости.


Итоговая структура типизированного API

Типизированный API Rollup в TypeScript формирует строгую систему контрактов:

  • конфигурация описывается через InputOptions и OutputOptions
  • результат сборки через RollupBuild и RollupOutput
  • плагины через Plugin и набор хук-типов
  • события watcher через discriminated unions
  • ошибки через RollupError

Такая модель делает сборочный процесс предсказуемым на уровне компиляции, снижая вероятность runtime-ошибок и повышая устойчивость архитектуры сборки в сложных приложениях.