{"id":13,"date":"2025-11-16T14:12:02","date_gmt":"2025-11-16T14:12:02","guid":{"rendered":"https:\/\/siewares.com\/?p=13"},"modified":"2025-11-16T14:16:51","modified_gmt":"2025-11-16T14:16:51","slug":"prefer-duration-objects-instead-numbers-in-typescript","status":"publish","type":"post","link":"https:\/\/siewares.com\/?p=13","title":{"rendered":"Prefer Duration Objects instead Numbers in Typescript"},"content":{"rendered":"\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"512\" height=\"341\" src=\"https:\/\/siewares.com\/wp-content\/uploads\/2025\/11\/Designer_2.png\" alt=\"\" class=\"wp-image-15\" style=\"width:645px;height:auto\" srcset=\"https:\/\/siewares.com\/wp-content\/uploads\/2025\/11\/Designer_2.png 512w, https:\/\/siewares.com\/wp-content\/uploads\/2025\/11\/Designer_2-300x200.png 300w\" sizes=\"auto, (max-width: 512px) 100vw, 512px\" \/><\/figure>\n\n\n\n<p>While coding, developers frequently deal with time durations\u200a\u2014\u200awhether it\u2019s for timeouts, intervals, cache lifecycles, or animations. The common approach is to use plain numbers to represent these durations, often in milliseconds. While this works, it introduces ambiguity and potential bugs.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h3 class=\"wp-block-heading is-style-text-subtitle is-style-text-subtitle--1\">The Problem with Plain&nbsp;Number<\/h3>\n\n\n\n<p>Consider the default JavaScript <code>setTimeout<\/code> method:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>setTimeout(() =&gt; doSomething(), 5000); <\/code><\/pre>\n\n\n\n<p>Quite often plain number are used as a parameter. For correct usage you have to rely on documentation, comments, or debugging to understand the unit.<\/p>\n\n\n\n<p>Furthermore this could lead to variables with comments or constants having big magic numbers.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const TIMEOUT = 1209600000; \/\/two weeks in millis\nconst TWO_WEEK_MILLIS = 1209600000;<\/code><\/pre>\n\n\n\n<p>&nbsp;Those constants created multiple times whereever needed. Sometimes developer tries to unmagic those number with patterns containing out the convertion to the next unit&nbsp;.<br><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const TWO_WEEK_MILLIS = 14 * 24 * 60 * 60 * 1000;<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<h3 class=\"wp-block-heading is-style-text-subtitle is-style-text-subtitle--2\">Real-World Example<\/h3>\n\n\n\n<p>In this example you can see a echart configuration, with such a construct. Maybe you already recognized that <code>maxValueSpan<\/code> property is milliseconds while the <code>minValueSpan<\/code> is in seconds. Here you do not get any compile error nor this is obvious while reading.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>return {\n      dataZoom: &#91;\n        {\n          maxValueSpan: 3_600 * 24 * 1000 * 365 * 2, \n          minValueSpan: 3_600,\n          disabled: true,\n          moveOnMouseMove: 'shift',\n          type: 'inside',\n          zoomOnMouseWheel: 'ctrl',\n          xAxisIndex: 0,\n        },\n      ],<\/code><\/pre>\n\n\n\n<p>Having just these numbers without any semantic as parameters, leads to that we can paste any number into this parameter. 2 weeks or 2 hours, the method will never know.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h3 class=\"wp-block-heading is-style-text-subtitle is-style-text-subtitle--3\">The Solution: Duration&nbsp;Objects<\/h3>\n\n\n\n<p>Instead of primitive numbers we can use duration objects. Good old moment.js does have them (see example), date-fns have it and i am pretty sure there a lot of other libs providing such classes (or you can implement it by your own)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>export const weeks = (w: number) =&gt; moment.duration(w, 'weeks');\nexport const hours = (h: number) =&gt; moment.duration(h, 'hours');\nexport const seconds = (s: number) =&gt; moment.duration(s, 'seconds');\n...<\/code><\/pre>\n\n\n\n<p>Exporting this function multiple times for the different units makes it easy to create a duration everybody is knowing what he is dealing with (like weeks(2))<\/p>\n\n\n\n<p>Now, instead of passing raw numbers, you pass duration objects:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const myTimeout = seconds(5);\n\nsetTimeout(()=&gt; {\n  doSomething();\n}, myTimeout.asMilliseconds());<\/code><\/pre>\n\n\n\n<p><br>This approach makes your code more readable and less error-prone. It also allows your functions to be agnostic of the time unit, converting it internally as needed.<\/p>\n\n\n\n<p>Even if a third-party library still consumes a number it becomes visible which target unit a developer wants to pass and you can convert it to the number as late as possible or create own wrapper consuming the duration object.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import moment, { Duration } from 'moment';\n\nfunction setSafeTimeout(callback: () =&gt; void,timeout: Duration) {\n  setTimeout(callback, timeout.asMilliseconds());\n}\n\nsetSafeTimeout(seconds(5));<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\"><\/pre>\n\n\n\n<h3 class=\"wp-block-heading is-style-text-subtitle is-style-text-subtitle--4\">Conclusion<\/h3>\n\n\n\n<p>Using duration objects instead of raw numbers is a simple yet powerful way to make your TypeScript code more robust, readable, and maintainable. Whether you use a library like Moment.js or implement your own lightweight duration helpers, the benefits are clear.<br>This approach can also be applied to other units, but durations are the most common inside code from my perspective.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>While coding, developers frequently deal with time durations\u200a\u2014\u200awhether it\u2019s for timeouts, intervals, cache lifecycles, or animations. The common approach is to use plain numbers to represent these durations, often in milliseconds. While this works, it introduces ambiguity and potential bugs. The Problem with Plain&nbsp;Number Consider the default JavaScript setTimeout method: Quite often plain number are [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-13","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/siewares.com\/index.php?rest_route=\/wp\/v2\/posts\/13","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/siewares.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/siewares.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/siewares.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/siewares.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=13"}],"version-history":[{"count":3,"href":"https:\/\/siewares.com\/index.php?rest_route=\/wp\/v2\/posts\/13\/revisions"}],"predecessor-version":[{"id":19,"href":"https:\/\/siewares.com\/index.php?rest_route=\/wp\/v2\/posts\/13\/revisions\/19"}],"wp:attachment":[{"href":"https:\/\/siewares.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=13"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/siewares.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=13"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/siewares.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=13"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}