typed-duration
Version:
Zero-dependency typed duration library for JavaScript
139 lines (89 loc) • 4.31 kB
Markdown
# Typed Duration

[](https://badge.fury.io/js/typed-duration)
A Zero-dependency typed duration library for JavaScript/TypeScript. Express and convert time durations with type-safety.
This library uses [Value Object Typing](https://medium.com/@hannespetri/type-safe-value-objects-in-typescript-d1b119c4f5cd) to allow you to express time durations in a type-safe way, and perform conversion between different units.
**Note**: requires TypeScript 3.8 or later
Version 1.x works on Node 10+
Version 2.x requires Node 16+
## Installation
Install the library to your project:
```
npm i typed-duration
```
## Use
Consider the following code:
```TypeScript
setTimeout(doSomething, 1000)
```
It's pretty clear that these are milliseconds, because you know the API. Typically, developers might do something like:
```TypeScript
setTimeout(doSomething, 5 * 60 * 1000) // In Five Minutes
```
With this library, you can do this:
```TypeScript
import { Duration } from 'typed-duration'
const { milliseconds, minutes } = Duration
const period = minutes.of(5)
setTimeout(doSomething, milliseconds.from(period)) // Every Five Minutes
```
Well, that looks like more code. Yes, it is. It is also _more semantically expressive_ of the programmer's intent, which makes it _better for maintenance_.
The situation is exacerbated when you expose a programming API that takes a time duration as a `number`. We all know that `setTimeout` takes milliseconds, but how do you communicate to consumers of your API what the time units are for `timeout` in _your_ API call?
You should, of course, document it, and put it in JSDoc comments so that they can get hinting in their IDE.
You could call it `timeoutSeconds` to make it clear that it expects seconds.
Or you could make it take a `TimeDuration` and allow them to pass in whatever they want, and convert it to the units you need, like this:
```TypeScript
import { Duration, TimeDuration } from 'typed-duration'
function executeLater(fn: () => void, delay: TimeDuration) {
setTimeout(fn, Duration.milliseconds.from(delay))
}
```
Now, consumers of this function can call it like this:
```TypeScript
import { Duration } from 'typed-duration'
const { milliseconds, seconds, minutes, hours, days } = Duration
// After 2.5 seconds
executeLater(doSomething, milliseconds.of(2500))
// After 10 seconds
executeLater(doSomething, seconds.of(10))
// After 15 minutes
executeLater(doSomething, minutes.of(15))
// After 3 hours
executeLater(doSomething, hours.of(3))
// After 6 days
executeLater(doSomething, days.of(6))
```
**#winning**
## Backward-compatible API
If you have an existing API you want to add this to, you can use the `MaybeTimeDuration` type, like this:
```TypeScript
import { Duration, MaybeTimeDuration } from 'typed-duration'
function executeLater(fn: () => void, period: MaybeTimeDuration) {
setTimeout(fn, Duration.milliseconds.from(period))
}
// You can pass in a typed duration, and it will convert to a number of milliseconds
executeLater(doSomething, Duration.seconds.from(20))
// a number will be allowed by the MaybeTimeDuration type
// and the milliseconds.from() call will simply pass it through
executeLater(doSomething, 2500)
```
## Logging
You can log times for user information in the format that the user specified them, including units, with `Duration.value.of`. You can supply an optional default unit to be used for untyped numbers (if you don't, it will just print the number).
For example:
```TypeScript
import { Duration, MaybeTimeDuration } from 'typed-duration'
function executeLater(fn: () => void, delay: MaybeTimeDuration) {
console.log(`Executing in ${Duration.value.of(delay, "ms")}...`)
setTimeout(fn, Duration.milliseconds.from(delay))
}
executeLater(doSomething, Duration.seconds.from(20))
// Executing in 20s...
executeLater(doSomething, Duration.milliseconds.from(350))
// Executing in 350ms...
executeLater(doSomething, Duration.hours.from(3))
// Executing in 3h...
executeLater(doSomething, 2500)
// Executing in 2500ms...
```
## Feature Requests, Bug Reports
See the [GitHub repo](https://github.com/jwulf/typed-duration).