{"id":21331457,"url":"https://github.com/eibens/unit","last_synced_at":"2026-04-12T22:44:56.585Z","repository":{"id":102373505,"uuid":"442178711","full_name":"eibens/unit","owner":"eibens","description":"Extensible, strongly-typed unit conversions in TypeScript for Deno.","archived":false,"fork":false,"pushed_at":"2023-04-23T19:20:55.000Z","size":16,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-22T13:48:11.085Z","etag":null,"topics":["conversion","deno","typescript","unit","utility"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eibens.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-12-27T14:11:49.000Z","updated_at":"2021-12-28T09:29:34.000Z","dependencies_parsed_at":null,"dependency_job_id":"e8b6e9bd-05c9-4376-b4f8-d915f46488e2","html_url":"https://github.com/eibens/unit","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eibens%2Funit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eibens%2Funit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eibens%2Funit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eibens%2Funit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eibens","download_url":"https://codeload.github.com/eibens/unit/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243809848,"owners_count":20351407,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["conversion","deno","typescript","unit","utility"],"created_at":"2024-11-21T22:33:26.195Z","updated_at":"2026-04-12T22:44:51.542Z","avatar_url":"https://github.com/eibens.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# unit\n\n[unit](#) is an extensible library for strongly-typed unit conversions in\nTypeScript for Deno.\n\n\u003c!-- badges --\u003e\n\n[![License](https://img.shields.io/github/license/eibens/unit?color=informational)](LICENSE)\n[![Repository](https://img.shields.io/github/v/tag/eibens/unit?label\u0026logo=github)](https://github.com/eibens/unit)\n[![ci](https://github.com/eibens/unit/actions/workflows/ci.yml/badge.svg)](https://github.com/eibens/unit/actions/workflows/ci.yml)\n[![codecov](https://codecov.io/gh/eibens/unit/branch/master/graph/badge.svg?token=OV98O91EJ1)](https://codecov.io/gh/eibens/unit)\n\n\u003c!-- /badges --\u003e\n\n# Conversions\n\nThe [`convert` function](convert.ts) converts a numeric `value` in a `source`\nunit to a value in a `target` unit using a `system` of conversions. For example,\nthe code below converts the value `0.5` from `\"hour\"` to `\"second\"` using a\n[predefined system](#predefined-systems), and tests whether the result is\n`1800`. The names of the units are strongly-typed:\n\n```ts\nimport { convert, SiTime } from \"./mod.ts\";\n\nconst result = convert({\n  value: 0.5,\n  source: \"hour\",\n  target: \"second\",\n  system: SiTime.getSystem(),\n});\n\nconsole.assert(result === 1800);\n```\n\n# Systems\n\nA system is a set of [`Conversion`](conversion.ts) objects. For example, the\ncode below defines conversions from `\"hour\"` to `\"minute\"` and from `\"minute\"`\nto `\"second\"`. Plugging this system into the `convert` function yields the same\nresult as before. Note how there is no explicit conversion function from\n`\"hour\"` to `\"second\"`, but an implicit conversion exists via the `\"minute\"`\nunit. The `convert` function automatically finds the `hour -\u003e minute -\u003e second`\npath and chains the conversion functions:\n\n```ts\nimport { Conversion, convert } from \"./mod.ts\";\n\ntype Unit =\n  | \"hour\"\n  | \"second\"\n  | \"minute\";\n\nfunction getSystem(): Conversion\u003cUnit\u003e[] {\n  return [{\n    source: \"hour\",\n    target: \"minute\",\n    apply: (value) =\u003e value * 60,\n  }, {\n    source: \"minute\",\n    target: \"second\",\n    apply: (value) =\u003e value * 60,\n  }];\n}\n\nconst result = convert({\n  value: 0.5,\n  source: \"hour\",\n  target: \"second\",\n  system: getSystem(),\n});\n\nconsole.assert(result === 1800);\n```\n\n## Parametric Systems\n\nSystems sometimes depend on external parameters. For example, in a\n[musical time unit system](systems/music_time.ts) a `tempo` parameter is needed\nto convert from `\"beat\"` to `\"second\"`. Parameters can be passed to the\n`getSystem` function:\n\n```ts\nimport { Conversion, convert } from \"./mod.ts\";\n\ntype Unit =\n  | \"beat\"\n  | \"second\";\n\ntype Options = {\n  tempo: number;\n};\n\nfunction getSystem(options: Options): Conversion\u003cUnit\u003e[] {\n  return [{\n    source: \"beat\",\n    target: \"second\",\n    apply: (value) =\u003e value * 60 / options.tempo,\n  }];\n}\n\nconst result = convert({\n  value: 1,\n  source: \"beat\",\n  target: \"second\",\n  system: getSystem({\n    tempo: 120,\n  }),\n});\n\nconsole.assert(result === 0.5);\n```\n\n## Generic Systems\n\nGeneric systems are not bound to a specific set of units and can thus be used as\ntemplates for other unit systems. For example, the\n[`Factor` system](systems/factor.ts) takes a `target` unit, numeric `factor`,\nand `source` unit, and returns a system that consists of two conversions: one\nmultiplies the `source` unit by the `factor` and one divides the `target` unit\nby the `factor`:\n\n```ts\nimport { Conversion, convert, Factor } from \"./mod.ts\";\n\ntype Unit =\n  | \"minute\"\n  | \"second\";\n\nconst result = convert({\n  value: 30,\n  source: \"second\",\n  target: \"minute\",\n  system: Factor.getSystem\u003cUnit\u003e(\"minute\", 60, \"second\"),\n});\n\nconsole.assert(result === 0.5);\n```\n\n## Composite Systems\n\nSince a system is an array of conversions, two systems can be merged by\nconcatenating their arrays. For example, one can build a system for converting\nbetween `\"hour\"`, `\"minute\"`, and `\"second\"` by concatenating two\n[`Factor` systems](systems/factor.ts):\n\n```ts\nimport { Conversion, convert, Factor } from \"./mod.ts\";\n\ntype Unit =\n  | \"hour\"\n  | \"second\"\n  | \"minute\";\n\nfunction getSystem(): Conversion\u003cUnit\u003e[] {\n  return [\n    ...Factor.getSystem(\"hour\", 60, \"minute\"),\n    ...Factor.getSystem(\"minute\", 60, \"second\"),\n  ];\n}\n\nconst result = convert({\n  value: 0.5,\n  source: \"hour\",\n  target: \"second\",\n  system: getSystem(),\n});\n\nconsole.assert(result === 1800);\n```\n\n## Predefined Systems\n\nThe package comes with predefined systems, each with a `Unit` type and a\n`getSystem` function that generates a minimal spanning-tree of conversions.\nWhile still very limited in number, they may serve as a starting point for\nbuilding custom systems:\n\n- [`SiTime`](systems/si_time.ts) is a constant system for SI time units.\n- [`MusicTime`](systems/music_time.ts) is a parametric system for musical time\n  units.\n- [`Factor`](systems/factor.ts) is a generic system for multiplicative\n  conversions.\n\n# Future Work\n\n- Unit abbreviations or aliases (e.g. `second = s`).\n- Unit parsing (e.g. `\"1s\" -\u003e [1, \"second\"]`).\n- Predefined systems for common units (e.g. weight, length).\n- Additive conversion (e.g. `1h2m3s -\u003e 1h + 2m + 3s`).\n- Multi-dimensional conversions (e.g. `1 m/s -\u003e 3.6 km/h`).\n- More generic systems (e.g. `Linear` for `K -\u003e °C`, `Exp` for `dB -\u003e ratio`).\n- Conversion DSL (e.g. `time(\"0.5h\").to(\"s\")`)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feibens%2Funit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feibens%2Funit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feibens%2Funit/lists"}