Перейти к содержимому

Declaration Merging & Module Augmentation

Уникальная фича TS, без которой не расширить lib.d.ts, jest, express и т.п. На интервью просят: «Как добавить req.user в Express?» — через module augmentation. Красный флаг — путать declare module с declare namespace, не знать про global augmentation.

Слияние interface и namespace:

interface Config { host: string }
interface Config { port: number } // сливается
const c: Config = { host: 'h', port: 80 };
// namespace + interface (companion)
class Service {}
namespace Service {
export const VERSION = '1.0';
export interface Options { retries: number }
}
const v = Service.VERSION;
const o: Service.Options = { retries: 3 };

Module augmentation — расширяем чужой модуль:

types/express.d.ts
import 'express';
declare module 'express-serve-static-core' {
interface Request {
user?: { id: string; role: 'admin' | 'user' };
}
}
// теперь в коде:
import type { Request } from 'express';
function h(req: Request) { return req.user?.id; }

Global augmentation — лезем в глобальные типы:

types/global.d.ts
export {}; // делает файл модулем
declare global {
interface Window {
analytics: { track(event: string): void };
}
// расширяем встроенный тип
interface Array<T> {
last(): T | undefined;
}
}
window.analytics.track('login');
[1, 2, 3].last(); // 3

Итог: Declaration merging работает у interface/namespace; для расширения внешних модулей — declare module ‘name’, для глобалей — declare global.