{"id":20215812,"url":"https://github.com/pallad-ts/compare","last_synced_at":"2026-05-08T20:31:42.409Z","repository":{"id":57134904,"uuid":"379540063","full_name":"pallad-ts/compare","owner":"pallad-ts","description":"Custom sorting inspired by Rust","archived":false,"fork":false,"pushed_at":"2022-12-05T16:23:25.000Z","size":307,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-15T05:05:20.331Z","etag":null,"topics":["comparison","custom-sorting","nodejs","sorting","value-object"],"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/pallad-ts.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-06-23T08:55:18.000Z","updated_at":"2021-12-19T20:26:47.000Z","dependencies_parsed_at":"2023-01-24T01:16:03.250Z","dependency_job_id":null,"html_url":"https://github.com/pallad-ts/compare","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pallad-ts%2Fcompare","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pallad-ts%2Fcompare/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pallad-ts%2Fcompare/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pallad-ts%2Fcompare/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pallad-ts","download_url":"https://codeload.github.com/pallad-ts/compare/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241652964,"owners_count":19997578,"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":["comparison","custom-sorting","nodejs","sorting","value-object"],"created_at":"2024-11-14T06:24:45.962Z","updated_at":"2026-05-08T20:31:37.382Z","avatar_url":"https://github.com/pallad-ts.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\t\u003ch1\u003ecompare ⬆️⬇️️\u003c/h1\u003e\n\t\u003cp\u003eCustom sorting inspired by Rust\u003c/p\u003e\n\u003c/div\u003e\n\n---\n[![CircleCI](https://circleci.com/gh/pallad-ts/compare/tree/master.svg?style=svg)](https://circleci.com/gh/pallad-ts/compare/tree/master)\n[![npm version](https://badge.fury.io/js/@pallad%2Fcompare.svg)](https://badge.fury.io/js/@pallad%2Fcompare)\n[![Coverage Status](https://coveralls.io/repos/github/pallad-ts/compare/badge.svg?branch=master)](https://coveralls.io/github/pallad-ts/compare?branch=master)\n[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)\n---\n\n![Example code](./assets/intro-code.png)\n\nSorting library inspired by [Rust's Ordering](https://doc.rust-lang.org/std/cmp/enum.Ordering.html).\n\nAllows to easy definition of comparison abilities for your objects, especially value objects.\n\n# Community\n\nJoin our [discord server](https://discord.gg/cbpxw93DnS)\n\n# Installation\n\n```shell\nnpm install @pallad/compare\n```\n\n# Usage\n\nComparing two values of same type\n\n```typescript\nimport {compare} from '@pallad/compare';\n\ncompare(1, 2).isLess // true\ncompare(1, 2).isGreater // false\ncompare(1, 2).isEqual // false\n```\n\n## Sorting\n\n`compare` first tries to leverage `compare` defined by `Comparable` interface if that is possible.\nOtherwise fallbacks to regular operators (`\u003c`, `==`, `\u003e`) comparison .\n\n```typescript\nimport {compare} from '@pallad/compare';\n\n[5, 1, 10].sort(compare); // [1, 5, 10]\n[5, 1, 10].sort(compare.reverse); // [10, 5, 1]\n```\n\n## Defining custom sorting for any values\n\nYou can define your own custom comparator that is used even if values are `Comparable` values.\n\n```typescript\nimport {compare} from '@pallad/compare';\n\ninterface Option {\n\ttype: string;\n\tvalue: string;\n}\n\nfunction comparator(a: Option, b: Option) {\n\treturn a.type.localeCompare(b.type);\n}\n\n\nconst aValue: Option = {\n\ttype: '2',\n\tvalue: 'Option 2'\n};\n\nconst bValue: Option = {\n\ttype: '1',\n\tvalue: 'Option 1'\n};\ncompare(aValue, bValue, comparator).isGreater // true\ncompare.reverse(aValue, bValue, comparator).isGreater // false\n```\n\nYou do not need to pass comparator all the time, just create own compare function.\n\n```typescript\nimport {createCompareWithComparator} from '@pallad/compare';\n\nconst customCompare = createCompareWithComparator(comparator);\ncustomCompare(aValue, bValue).isGreater // true\ncustomCompare.reverse(aValue, bValue).isGreater // false\n```\n\n## Defining custom sorting for value objects\n\n```typescript\nimport {Comparable, Equal, Less, Greater} from '@pallad/compare';\n\nclass Money implements Comparable {\n\tconstructor(readonly value: number, readonly currency: string) {\n\t}\n\n\tcompare(another: Money) {\n\t\tif (another.currency !== this.currency) {\n\t\t\tthrow new Error('Cannot compare values with different currencies');\n\t\t}\n\n\t\tif (another.value === this.value) {\n\t\t\treturn Equal;\n\t\t} else if (this.value \u003c another.value) {\n\t\t\treturn Less\n\t\t}\n\t\treturn Greater;\n\t}\n}\n\n\nconst amountA = new Money(100, 'BGP');\nconst amountB = new Money(200, 'BGP');\n\namountA.compare(amountB) // Less\n\n// uses `compare` since it is defined\ncompare(amountA, amountB); // Less\n```\n\n# Explanation\n\nAs in Rust's `Ordering` - `@pallad/compare` uses 3 immutable objects to describe the comparison result.\n\nThe result could be:\n\n* `Less`\n* `Equal`\n* `Greater`\n\nEach of them implements following shape:\n\n```typescript\ninterface Result {\n\ttype: 'equal' | 'less' | 'greater',\n\t/**\n\t * Indicates that value is lower\n\t */\n\tisLess: boolean;\n\t/**\n\t * Indicates that values are equal\n\t */\n\tisEqual: boolean;\n\t/**\n\t * Indicates that values are not equal (less or greater only)\n\t */\n\tisNotEqual: boolean;\n\t/**\n\t * Indicates that value is less or equal\n\t */\n\tisLessOrEqual: boolean;\n\t/**\n\t * Indicates that value is greater or equal\n\t */\n\tisGreaterOrEqual: boolean;\n\t/**\n\t * Indicates that value is greater\n\t */\n\tisGreater: boolean;\n\n\t/**\n\t * Maps result to another value\n\t */\n\tmap(ifLess: T1, ifEqual: T2, ifGreater: T3): T1 | T2 | T3;\n\n\tmap({less: T1, equal: T2, greater: T3}): T1 | T2 | T3;\n\n\t/**\n\t * Returns opposite value to current one\n\t *\n\t * Less -\u003e Greater\n\t * Equal -\u003e Equal\n\t * Greater -\u003e Less\n\t */\n\treverse: Result;\n\t/**\n\t * Just numeric value you can use in `.sort` functions\n\t */\n\tsortResult: 0 | -1 | 1,\n\t/**\n\t * Just numeric value you can use in `.sort` functions to reverse sorting\n\t */\n\tsortResultReversed: 0 | -1 | 1,\n}\n```\n\n# Mapping\n\nYou can map comparison result to any other value\n\n```typescript\nimport {compare} from '@pallad/compare';\n\n// using arguments for each value\nconst r1 = compare(1, 5).map('less', 'equal', 'greater') // 'less'\ntype R1 = typeof r1; // 'less' | 'equal' | 'greater'  \n\n// using object\nconst r2 = compare(1, 5).map({\n\tless: 'less',\n\tequal: 'equal',\n\tgreater: 'greater'\n}) // 'less'\n\ntype R2 = typeof r2; // 'less' | 'equal' | 'greater'\n```\n\n## Mapping to boolean\n\nBefore your try to map to booleans, think if currently available helpers are not good enough\n\n```typescript\nimport {compare} from '@pallad/compare';\n\ncompare(1, 10).map(false, true, false); // Too explicit ⚠️\ncompare(1, 10).isEqual // better 👌\n\ncompare(1, 10).map(true, true, false); // Too explicit ⚠️\ncompare(1, 10).isLessOrEqual // better 👌\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpallad-ts%2Fcompare","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpallad-ts%2Fcompare","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpallad-ts%2Fcompare/lists"}