@trt-web/core
v1.7.1
Published
Framework-agnostic TypeScript utilities for everyday web application development.
Maintainers
Readme
@trt-web/core
Introduction
@trt-web/coreis a framework-agnostic TypeScript toolkit for common web application tasks.- It provides focused, strongly typed utilities for dates, DOM, files, images, objects, strings, numbers, timing, workers, and more.
- Use the utilities independently in browser applications, shared packages, and framework projects.
Why @trt-web/core?
- Framework-agnostic and suitable for TypeScript or JavaScript applications.
- Small, reusable utilities with predictable APIs.
- Strong typing for common application and Web Platform tasks.
- Modular APIs that can be adopted without changing application architecture.
Install
npm install @trt-web/coreyarn add @trt-web/corebun add @trt-web/coreCLI
- The package includes
trt-core, a CLI for discovering utilities, inspecting methods and examples, and generating static documentation.
npx trt-core
npx trt-core --list
npx trt-core info cleanObj
npx trt-core docsFor Contributors
- Contributions and improvements are welcome. See
CONTRIBUTING.mdfor development, testing, and pull request guidelines. - Contact:
- Github: therightthings/trt-web
- NPM: @trt-web/core
- Email: [email protected] (Nam Nguyen)
trt.worker
Worker utilities for creating and running Web Workers.
createWorker
Create a Web Worker from a function.
Methods
createWorker<T, R>(handler: (value: T) => R): Worker: create a Web Worker from a function.
Examples
import { trt } from '@trt-web/core';
const worker = trt.worker.createWorker((value: number) => {
return value * 2;
});
worker.terminate();
console.log(worker instanceof Worker); // truerunWorker
Run a function in a Web Worker and resolve its result.
Methods
runWorker<T, R>(handler: (value: T) => R, value: T): Promise<R>: run a function in a Web Worker and resolve its result.
Examples
import { trt } from '@trt-web/core';
const sum = await trt.worker.runWorker(
(values: number[]) => {
return values.reduce((total, value) => total + value, 0);
},
[2, 3],
);
console.log(sum); // 5trt.date
Date and time utilities for generating timestamps and resolving date ranges.
generateTimestamp
generate a timestamp value.
Methods
generateTimestamp(): string: generate a timestamp value.
Examples
import { trt } from '@trt-web/core';
console.log(trt.date.generateTimestamp()); // '2026-07-25T...Z'getDateRange
resolve common preset ranges and dynamic ranges into startDate / endDate.
Methods
getDateRange(range: RangeDate | DynamicRangeDate, rootDate?: Date): { startDate: string; endDate: string }: resolve a date range into start and end dates.
Examples
import { trt } from '@trt-web/core';
console.log(trt.date.getDateRange('this_week'));
const rootDate = new Date('2026-07-03T17:00:00.000Z');
console.log(trt.date.getDateRange({ value: 3, unit: 'day' }, rootDate)); // { startDate: '2026-06-30', endDate: '2026-07-03' }
console.log(trt.date.getDateRange('last_7_days', rootDate)); // { startDate: '2026-06-27', endDate: '2026-07-03' }
console.log(trt.date.getDateRange('today', rootDate)); // { startDate: '2026-07-03', endDate: '2026-07-03' }
console.log(trt.date.getDateRange('yesterday', rootDate)); // { startDate: '2026-07-02', endDate: '2026-07-03' }
console.log(trt.date.getDateRange('last_30_days', rootDate)); // { startDate: '2026-06-04', endDate: '2026-07-03' }
console.log(trt.date.getDateRange('this_month', rootDate)); // { startDate: '2026-07-01', endDate: '2026-07-03' }
console.log(trt.date.getDateRange('this_year', rootDate)); // { startDate: '2026-01-01', endDate: '2026-07-03' }
console.log(trt.date.getDateRange({ value: 2, unit: 'week' }, rootDate)); // { startDate: '2026-06-19', endDate: '2026-07-03' }
console.log(trt.date.getDateRange({ value: 1, unit: 'month' }, rootDate)); // { startDate: '2026-06-03', endDate: '2026-07-03' }
console.log(trt.date.getDateRange({ value: 1, unit: 'year' }, rootDate)); // { startDate: '2025-07-03', endDate: '2026-07-03' }trt.dom
DOM utilities for inspecting elements, generating colors, and managing CSS variables.
generateRandomColor
generate a random color value.
Methods
generateRandomColor(config?: GenerateColorConfig): string: generate a random color value.
Examples
import { trt } from '@trt-web/core';
const color = trt.dom.generateRandomColor({ format: 'rgb', opacity: 0.5 });
console.log(color); // 'rgba(36, 149, 97, 0.5)' (random RGB values)
console.log(trt.dom.generateRandomColor({ format: 'hex', opacity: 0.5 })); // '#RRGGBBAA' (8 lowercase hex digits)
console.log(trt.dom.generateRandomColor()); // '#RRGGBB' (lowercase random hex color)
console.log(trt.dom.generateRandomColor({ format: 'rgb' })); // 'rgb(R, G, B)'getElementInfo
read size and position details from an element.
Methods
getElementInfo(element: HTMLElement): object: read size and position details from an element.
Examples
import { trt } from '@trt-web/core';
const info = trt.dom.getElementInfo(document.querySelector('#app')!);
console.log(info.area.rect); // { width: 640, height: 480 }
console.log(info.horizontal, info.vertical); // scroll and position detailsvarCSS
read or write a CSS custom property.
Methods
varCSS(name: string, value?: string): string: read or write a CSS custom property.
Examples
import { trt } from '@trt-web/core';
trt.dom.varCSS('--brand-color', '#2563eb');
console.log(trt.dom.varCSS('--brand-color')); // '#2563eb'trt.file
File utilities for converting, loading, resizing, and processing files and images.
compressImageFile
compress and resize image files.
Methods
compressImageFile(file: File, config?: { maxWidth?: number; outputFormat?: 'image/jpeg' | 'image/webp'; quality?: number }): Promise<File>: compress and resize an image file.
Examples
import { trt } from '@trt-web/core';
const input = document.querySelector<HTMLInputElement>('#image-input');
const file = input?.files?.[0];
if (file) {
const compressed = await trt.file.compressImageFile(file, {
maxWidth: 1200,
quality: 0.8,
});
console.log(compressed instanceof File, compressed.type); // true 'image/jpeg'
}convertFileSize
convert file size values between byte units.
Methods
convertFileSize(value: number, unit: string, config?: { decimalPlaces?: number }): number: convert a file size between units.
Examples
import { trt } from '@trt-web/core';
console.log(trt.file.convertFileSize(1024, 'byte:kb')); // 1
console.log(trt.file.convertFileSize(2, 'Gb:Mb')); // 2048
console.log(trt.file.convertFileSize(1.5, 'Mb:byte')); // 1572864
console.log(trt.file.convertFileSize(1, 'Mb:Gb', { decimalPlaces: 4 })); // 0.001
try {
trt.file.convertFileSize(Number.POSITIVE_INFINITY, 'byte:kb');
} catch (error) {
console.log((error as Error).message); // 'value must be a finite number'
}fileToDataUrl
convert a file to a data URL.
Methods
fileToDataUrl(file: File): Promise<string>: convert a file to a data URL.
Examples
import { trt } from '@trt-web/core';
const input = document.querySelector<HTMLInputElement>('#file-input');
const file = input?.files?.[0];
if (file) {
const dataUrl = await trt.file.fileToDataUrl(file);
console.log(dataUrl.startsWith('data:')); // true
}fileToObjectUrl
convert a file to an object URL.
Methods
fileToObjectUrl(source: Blob | File | string, options?: { type?: string }): string: convert a Blob, File, or data URL to an object URL.
Examples
import { trt } from '@trt-web/core';
const input = document.querySelector<HTMLInputElement>('#file-input');
const file = input?.files?.[0];
if (file) {
const objectUrl = trt.file.fileToObjectUrl(file);
console.log(objectUrl.startsWith('blob:')); // true
URL.revokeObjectURL(objectUrl);
}getImageSize
inspect image dimensions.
Methods
getImageSize(blob: File | string, options?: { revokeObjectUrl?: boolean }): Promise<{ width: number; height: number }>: inspect image dimensions.
Examples
import { trt } from '@trt-web/core';
const imageSize = await trt.file.getImageSize('/assets/photo.jpg');
console.log(imageSize); // { width: 1920, height: 1080 } for a 1920x1080 imageloadImage
load an image element from a source.
Methods
loadImage(src: string): Promise<HTMLImageElement>: load an image element from a source.
Examples
import { trt } from '@trt-web/core';
const image = await trt.file.loadImage('/assets/photo.jpg');
console.log(image instanceof HTMLImageElement, image.complete); // true truetrt.number
Number utilities for ratings, geographic distance, formatting, and random values.
calcBayesianRating
calculate a Bayesian-style rating using a global average prior.
Methods
calcBayesianRating(params: { ratingAvg: number; ratingCount: number; globalAvg: number; minimumVotesThreshold?: number }): number: calculate a Bayesian-style rating using a global average prior.
Examples
import { trt } from '@trt-web/core';
console.log(
trt.number.calcBayesianRating({
ratingAvg: 4.5,
ratingCount: 6,
globalAvg: 3.5,
minimumVotesThreshold: 2,
}),
); // 4.25
console.log(trt.number.calcBayesianRating({ ratingAvg: 4.8, ratingCount: 0, globalAvg: 3.6 })); // 3.6
console.log(trt.number.calcBayesianRating({ ratingAvg: 5, ratingCount: 1, globalAvg: 3 })); // 3.182calcHaversineDistance
calculate distance between two latitude/longitude points.
Methods
calcHaversineDistance(from: Point, to: Point, options?: { unit?: 'km' | 'm' }): number: calculate distance between two latitude/longitude points.
Examples
import { trt } from '@trt-web/core';
console.log(
trt.number.calcHaversineDistance(
{ latitude: 36.12, longitude: -86.67 },
{ latitude: 33.94, longitude: -118.4 },
),
); // 2886.444 (km, approximately)
console.log(
trt.number.calcHaversineDistance(
{ latitude: 10.123, longitude: 106.456 },
{ latitude: 10.123, longitude: 106.456 },
),
); // 0
console.log(
trt.number.calcHaversineDistance(
{ latitude: 10.123, longitude: 106.456 },
{ latitude: 10.124, longitude: 106.457 },
{ unit: 'm' },
),
); // distance in meterscalcSimpleBayesianRating
calculate a weighted rating without a prior.
Methods
calcSimpleBayesianRating(params: { ratingAvg: number; ratingCount: number; minimumVotesThreshold?: number }): number: calculate a weighted rating without a prior.
Examples
import { trt } from '@trt-web/core';
console.log(
trt.number.calcSimpleBayesianRating({
ratingAvg: 4.8,
ratingCount: 12,
minimumVotesThreshold: 8,
}),
); // 2.88
console.log(trt.number.calcSimpleBayesianRating({ ratingAvg: 4.8, ratingCount: 0 })); // 0formatViewCount
format a view count into compact notation like 1.2k.
Methods
formatViewCount(value: number, config?: FormatViewCountConfig): string: format a view count into compact notation like1.2k.
Examples
import { trt } from '@trt-web/core';
console.log(trt.number.formatViewCount(1000)); // '1k'
console.log(trt.number.formatViewCount(1234)); // '1.2k'
console.log(trt.number.formatViewCount(999)); // '999'
console.log(trt.number.formatViewCount(1250, { decimalPlaces: 2 })); // '1.25k'
console.log(trt.number.formatViewCount(1250, { decimalPlaces: 0 })); // '1k'
console.log(trt.number.formatViewCount(1_250_000)); // '1.3m'
console.log(trt.number.formatViewCount(2_500_000, { uppercase: true })); // '2.5M'
console.log(trt.number.formatViewCount(2_500_000_000)); // '2.5b'generateRandomNumber
generate integer or decimal numbers in a range.
Methods
generateRandomNumber(min: number, max: number, config?: GenerateRandomNumberConfig): number: generate an integer or decimal number in a range.
Examples
import { trt } from '@trt-web/core';
console.log(trt.number.generateRandomNumber(1, 10)); // integer from 1 to 10
console.log(trt.number.generateRandomNumber(1, 2, { decimal: true, decimalPlaces: 3 })); // decimal from 1.000 to 2.000
try {
trt.number.generateRandomNumber(1.2, 3);
} catch (error) {
console.log((error as Error).message); // 'min and max must be integers'
}trt.object
Object utilities for cleaning nested data and removing duplicate objects.
cleanObj
remove empty values from objects and nested structures.
Methods
cleanObj<T extends object>(obj: Partial<T>): Partial<T>: remove empty values from objects and nested structures.
Examples
import { trt } from '@trt-web/core';
console.log(trt.object.cleanObj({ name: 'Alice', empty: '', value: null })); // { name: 'Alice' }
console.log(
trt.object.cleanObj({
a: undefined,
d: 0,
e: false,
nested: { value: null, name: 'Alice' },
}),
); // { d: 0, e: false, nested: { name: 'Alice' } }
console.log(trt.object.cleanObj({ a: null, b: undefined, c: '' })); // {}
const circular: Record<string, unknown> = {};
circular.self = circular;
try {
trt.object.cleanObj(circular);
} catch (error) {
console.log((error as Error).message); // 'Circular reference detected'
}removeDuplicateObjects
deduplicate object arrays while preserving structure.
Methods
removeDuplicateObjects<T>(array: T[], filterFn?: (item: T) => string): T[]: deduplicate an object array while preserving its structure.
Examples
import { trt } from '@trt-web/core';
console.log(trt.object.removeDuplicateObjects([{ id: 1 }, { id: 1 }, { id: 2 }])); // [{ id: 1 }, { id: 2 }]
console.log(
trt.object.removeDuplicateObjects(
[
{ id: 1, name: 'A' },
{ id: 1, name: 'B' },
{ id: 2, name: 'C' },
],
(item) => String(item.id),
),
); // [{ id: 1, name: 'A' }, { id: 2, name: 'C' }]trt.timing
Timing utilities for delaying, debouncing, and throttling function execution.
debounce
debounce function calls.
Methods
debounce<T extends (...args: any[]) => any>(func: T, wait?: number | TimeConfig, options?: DebounceOptions): DebouncedFunction<T>: debounce function calls.
Examples
import { trt } from '@trt-web/core';
const search = trt.timing.debounce((keyword: string) => {
return keyword.toUpperCase();
}, 300);
search('indexed database');
console.log(search.pending()); // true
console.log(search.flush()); // 'INDEXED DATABASE'
search.cancel();
console.log(search.pending()); // false
const leadingSearch = trt.timing.debounce(
(keyword: string) => {
return keyword.toUpperCase();
},
300,
{
leading: true,
trailing: false,
},
);
console.log(leadingSearch('first')); // 'FIRST'throttle
throttle function calls.
Methods
throttle<T extends (...args: any[]) => any>(func: T, wait?: number | TimeConfig, options?: ThrottleOptions): ThrottledFunction<T>: throttle function calls.
Examples
import { trt } from '@trt-web/core';
const handleScroll = trt.timing.throttle(() => {
return window.scrollY;
}, 100);
console.log(handleScroll()); // current window.scrollY value
console.log(handleScroll.pending()); // true or false, depending on the throttle window
handleScroll.cancel();
const trailing = trt.timing.throttle(
(value: string) => {
return value;
},
100,
{
leading: false,
trailing: true,
},
);
trailing('queued');
console.log(trailing.pending()); // true
console.log(trailing.flush()); // 'queued'wait
pause execution for a duration.
Methods
wait(time: number | TimeConfig): Promise<void>: pause execution for a duration.
Examples
import { trt } from '@trt-web/core';
await trt.timing.wait({ value: 10, unit: 'millisecond' });
console.log('ready'); // 'ready' (after at least 10 ms)trt.string
String utilities for capitalization, hashing, identifiers, random values, and search keys.
capitalize
capitalize a string or selected string fields in an object.
Methods
capitalize(data: string, config?: CapitalizeStringConfig): string: capitalize a string.capitalize<T extends Record<string, unknown>>(data: T, config?: CapitalizeObjectConfig<T>): T: capitalize selected string fields in an object.
Examples
import { trt } from '@trt-web/core';
const profile = {
firstName: 'alice',
lastName: 'nguyen van an',
bio: 'frontend developer',
age: 30,
};
console.log(trt.string.capitalize('hello')); // 'Hello' (string mode defaults to 'first')
console.log(trt.string.capitalize('hello world', { mode: 'first' })); // 'Hello world'
console.log(trt.string.capitalize('hello world', { mode: 'words' })); // 'Hello World'
console.log(trt.string.capitalize(profile)); // same object values; no fields selected
console.log(trt.string.capitalize(profile, { first: ['firstName'] })); // { firstName: 'Alice', lastName: 'nguyen van an', bio: 'frontend developer', age: 30 }
console.log(trt.string.capitalize(profile, { words: ['lastName', 'bio'] })); // { firstName: 'alice', lastName: 'Nguyen Van An', bio: 'Frontend Developer', age: 30 }
const article = {
title: 'hello world',
author: 'alice nguyen',
summary: '',
};
console.log(trt.string.capitalize(article, { first: ['title'], words: ['author'] })); // { title: 'Hello world', author: 'Alice Nguyen', summary: '' }
console.log(trt.string.capitalize({ title: null }, { first: ['title'] })); // { title: '' }generateHash
create a hash string.
Methods
generateHash(data: unknown): Promise<string>: create a SHA-256 hash string from a value.
Examples
import { trt } from '@trt-web/core';
console.log(await trt.string.generateHash('hello')); // '5aa762ae383fbb727af3c7a36d4940a5b8c40a989452d2304fc958ff3f354e7a'generateId
generate a unique identifier.
Methods
generateId(): string: generate a UUID identifier.
Examples
import { trt } from '@trt-web/core';
console.log(trt.string.generateId().length); // 36 (UUID string)removeTones
normalize accents, separators, and non-Latin characters for searchable text.
Methods
removeTones(value: string, config?: { separator?: string; removeNonLatinAscii?: boolean }): string: normalize text into a lowercase searchable value.
Examples
import { trt } from '@trt-web/core';
console.log(trt.string.removeTones('Đắk Lắk')); // 'dak lak'
console.log(
trt.string.removeTones('Café & Tea', {
separator: '-',
}),
); // 'cafe-tea'
console.log(trt.string.removeTones('中文 Café', { removeNonLatinAscii: false })); // '中文 cafe'generateRandomString
generate a random string.
Methods
generateRandomString(length?: number): string: generate a random hexadecimal string from the requested number of random bytes. The result containslength * 2hexadecimal characters.
Examples
import { trt } from '@trt-web/core';
console.log(trt.string.generateRandomString(8).length); // 16generateSortOrderKey
Generate fixed-width sortable keys (64 characters) and compare them safely.
Methods
generateSortOrderKey(config?: { previous?: string; next?: string }): string: generate a key between two existing keys, or before/after one key.compareSortOrderKey(first: string, second: string): -1 | 0 | 1: compare keys with the same ordering rules asgenerateSortOrderKey; use it as theArray.prototype.sort()comparator.
Examples
import { trt } from '@trt-web/core';
// No config: generate a key near the middle of the available range.
const first = trt.string.generateSortOrderKey();
// next only: generate a key before `first`.
const beforeFirst = trt.string.generateSortOrderKey({ next: first });
// previous only: generate a key after `first`.
const afterFirst = trt.string.generateSortOrderKey({ previous: first });
// previous and next: generate a key strictly between them.
const between = trt.string.generateSortOrderKey({
previous: first,
next: afterFirst,
});
// `previous` must be smaller than `next`, with at least one rank available between them.
// Both keys must be fixed-width and valid; empty, variable-width, or unsupported keys throw.
const items = [{ order: afterFirst }, { order: beforeFirst }, { order: between }, { order: first }];
items.sort((a, b) => trt.string.compareSortOrderKey(a.order, b.order));Always pass compareSortOrderKey to Array.prototype.sort() instead of comparing keys manually. Existing legacy variable-width keys must be migrated before using the generator or comparator.
generateSearchKeys
build searchable prefixes and tokens from text.
Methods
generateSearchKeys(value: string, options?: { minPrefixLength?: number; maxPrefixLength?: number; includePhrasePrefixes?: boolean; includeAcronym?: boolean }): string[]: build normalized searchable keys, word prefixes, phrase prefixes, and an optional acronym.
Examples
import { trt } from '@trt-web/core';
console.log(trt.string.generateSearchKeys('Café')); // normalized keys without tones
console.log(
trt.string.generateSearchKeys('Đắk Lắk', {
minPrefixLength: 1,
includePhrasePrefixes: false,
includeAcronym: false,
}),
); // ['d', 'da', 'dak', 'l', 'la', 'lak']
console.log(trt.string.generateSearchKeys('中文 😀')); // []utils
Shared validation, conversion, and error-handling helpers.
checkCircularReferences
detect circular references before serializing or processing nested data.
Methods
checkCircularReferences(value: unknown): void: throw when a circular reference is found.
Examples
import { checkCircularReferences } from '@trt-web/core';
const value: Record<string, unknown> = {};
value.self = value;
try {
checkCircularReferences(value);
} catch (error) {
console.log((error as Error).message); // 'Circular reference detected'
}isType
check a value or a field against a supported runtime type.
Methods
isType(type: ValueType, source: unknown, field?: PropertyKey): boolean: check a value or an object field type.
Examples
import { isType } from '@trt-web/core';
console.log(isType('array', [1, 2])); // true
console.log(isType('string', { name: 'Alice' }, 'name')); // true
console.log(isType('null', null)); // trueAll assert* methods accept an optional { path?: string } option for error messages. The path defaults to value.
assertNumber
assert a number and optionally apply one numeric constraint.
Methods
assertNumber(value: unknown, option?: { path?: string }): throw when the value is not a number..finite(): void: require a finite number..integer(): void: require an integer..nonNegative(): void: require a finite number greater than or equal to zero..positive(): void: require a finite number greater than zero..nonNegativeInteger(): void: require a non-negative integer..positiveInteger(): void: require a positive integer.
Examples
import { assertNumber } from '@trt-web/core';
assertNumber(12.5).finite();
assertNumber(3).positiveInteger();assertString
assert a string and optionally require it to contain non-whitespace characters.
Methods
assertString(value: unknown, option?: { path?: string }): throw when the value is not a string..nonEmpty(): void: require a non-empty, non-whitespace string.
Examples
import { assertString } from '@trt-web/core';
assertString('Alice').nonEmpty();assertArray
assert an array and optionally require it to contain at least one item.
Methods
assertArray(value: unknown, option?: { path?: string }): throw when the value is not an array..nonEmpty(): void: require a non-empty array.
Examples
import { assertArray } from '@trt-web/core';
assertArray([1, 2, 3]).nonEmpty();assertFunction
assert that a value is a function.
Methods
assertFunction(value: unknown, option?: { path?: string }): void: throw when the value is not a function.
assertBoolean
assert that a value is a boolean.
Methods
assertBoolean(value: unknown, option?: { path?: string }): void: throw when the value is not a boolean.
assertObject
assert that a value is a non-null, non-array object.
Methods
assertObject(value: unknown, option?: { path?: string }): void: throw when the value is not an object.
assertBigint
assert that a value is a bigint.
Methods
assertBigint(value: unknown, option?: { path?: string }): void: throw when the value is not a bigint.
assertSymbol
assert that a value is a symbol.
Methods
assertSymbol(value: unknown, option?: { path?: string }): void: throw when the value is not a symbol.
requireBrowserEnv
require a browser environment before using browser-only APIs.
Methods
requireBrowserEnv(config?: { message?: string }): boolean: throw whenwindowordocumentis unavailable.
Examples
import { requireBrowserEnv } from '@trt-web/core';
requireBrowserEnv(); // true in a browser; throws in a non-browser runtimeroundToDecimals
round a finite number to a non-negative integer number of decimal places.
Methods
roundToDecimals(value: number, decimalPlaces: number): number: round a number to the requested precision.
Examples
import { roundToDecimals } from '@trt-web/core';
console.log(roundToDecimals(12.3456, 2)); // 12.35stringify
serialize values after checking for circular references.
Methods
stringify(value: unknown): string: serialize a value as JSON or throw for circular data.
Examples
import { stringify } from '@trt-web/core';
console.log(stringify({ name: 'Alice', active: true })); // '{"name":"Alice","active":true}'toError
normalize an unknown thrown value into an Error instance.
Methods
toError(error: unknown, fallbackMessage: string): Error: return an existing error or create one from the value/fallback message.
Examples
import { toError } from '@trt-web/core';
try {
await fetch('/api/profile');
} catch (error) {
const normalizedError = toError(error, 'Unable to load profile');
console.error(normalizedError.message);
}toMs
convert a number or time config into milliseconds.
Methods
toMs(config: TimeConfig | number): number: convert milliseconds, seconds, minutes, hours, or days to milliseconds.
Examples
import { toMs } from '@trt-web/core';
console.log(toMs(250)); // 250
console.log(toMs({ value: 2, unit: 'second' })); // 2000
console.log(toMs({ value: 1, unit: 'hour' })); // 3600000