Библиотека устанавливается стандартным способом через менеджеры пакетов:
npm install timeago.js
или
yarn add timeago.js
В современных TypeScript-проектах пакет уже содержит встроенные типы,
поэтому дополнительная установка @types/* чаще всего не
требуется. Это важный момент: начиная с актуальных версий, типизация
распространяется вместе с самой библиотекой, что упрощает интеграцию и
снижает вероятность конфликтов версий.
Поддерживаются несколько вариантов импорта в зависимости от конфигурации проекта.
import { format } from 'timeago.js';
const result: string = format(Date.now() - 60000);
import * as timeago from 'timeago.js';
const result = timeago.format(new Date());
const timeago = require('timeago.js');
console.log(timeago.format(new Date()));
При использовании TypeScript в строгом режиме предпочтение обычно отдается ESM-варианту, так как он обеспечивает лучшую статическую проверку типов и tree-shaking в сборщиках.
Ключевая функция библиотеки — format. В TypeScript она
имеет строго определённую сигнатуру:
format(input: string | number | Date, locale?: string, options?: object): string
Основные особенности типизации:
input принимает:
Date — объект датыnumber — timestamp в миллисекундахstring — строковое представление датыВозвращаемое значение всегда string
locale опционален и используется для локализации
вывода
Пример с явной типизацией:
import { format } from 'timeago.js';
const createdAt: Date = new Date('2024-01-01');
const timeLabel: string = format(createdAt);
При включённом strict: true в tsconfig.json
библиотека корректно работает без дополнительных настроек:
{
"compilerOptions": {
"strict": true,
"moduleResolution": "node",
"esModuleInterop": true
}
}
Особое внимание стоит уделить флагу esModuleInterop,
который влияет на корректность импорта CommonJS-модулей.
Библиотека поддерживает локали через регистрацию языков. В TypeScript это оформляется через расширение типов и регистрацию функции локали.
Пример регистрации локали:
import { register } from 'timeago.js';
register('ru', (number: number, index: number): [string, string] => {
return [
['только что', 'через %s секунд'],
['1 минуту назад', 'через 1 минуту'],
['%s минут назад', 'через %s минут'],
['1 час назад', 'через 1 час'],
['%s часов назад', 'через %s часов'],
['1 день назад', 'через 1 день'],
['%s дней назад', 'через %s дней'],
][index];
});
Тип возвращаемого значения функции локали строго фиксирован:
(number: number, index: number) => [string, string]
Это важно для предотвращения ошибок в структуре массива переводов.
import { format } from 'timeago.js';
const date = new Date();
const result = format(date, 'ru');
TypeScript гарантирует, что второй аргумент соответствует зарегистрированным локалям (в зависимости от конфигурации проекта может быть расширен вручную через declaration merging).
При необходимости добавления собственных локалей в больших проектах используется расширение типов.
Пример декларации:
declare module 'timeago.js' {
interface Locales {
ru: string;
en: string;
custom: string;
}
}
Такой подход позволяет:
В React-проектах библиотека часто используется для отображения “времени назад”.
import { useEffect, useState } from 'react';
import { format } from 'timeago.js';
interface Props {
date: Date;
}
export function TimeLabel({ date }: Props) {
const [value, setValue] = useState<string>(() => format(date));
useEffect(() => {
const id = setInterval(() => {
setValue(format(date));
}, 10000);
return () => clearInterval(id);
}, [date]);
return <span>{value}</span>;
}
TypeScript обеспечивает:
В современных сборках дополнительных настроек обычно не требуется.
import { format } from 'timeago.js';
Vite автоматически обрабатывает ESM и TypeScript-типы.
При использовании старых конфигураций важно проверить:
resolve.extensions включает .tsts-loader или babel-loader с
TypeScript presetРекомендуется использовать @rollup/plugin-typescript для
корректной обработки типов.
Ошибка возникает при смешении ESM и CommonJS:
// ошибка при неправильной конфигурации
import timeago from 'timeago.js';
Решение — использовать:
import * as timeago from 'timeago.js';
или включить esModuleInterop.
format('2024-01-01'); // string допустим, но может приводить к неоднозначности
Строгий вариант:
format(new Date('2024-01-01'));
При динамической регистрации локалей TypeScript не всегда может вывести строгий union-тип. В таких случаях используется явное расширение интерфейсов.
В крупных TypeScript-проектах часто создают обёртки над библиотекой:
import { format } from 'timeago.js';
export function formatTimeAgo(date: Date): string {
return format(date, 'ru');
}
Такой подход:
При работе с серверными данными важно учитывать типизацию DTO:
interface PostDTO {
id: number;
createdAt: string;
}
function mapPost(post: PostDTO) {
return {
...post,
createdAtLabel: format(new Date(post.createdAt))
};
}
TypeScript обеспечивает контроль преобразования строковой даты в
объект Date, что критично для корректной работы
форматирования времени.