Skip to content

Commit

Permalink
feat: support boolean values
Browse files Browse the repository at this point in the history
  • Loading branch information
jvandenaardweg committed Nov 16, 2022
1 parent be72859 commit 29c32c9
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 4 deletions.
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ blogPosts.sort(sortByProperty('author.name', 'asc'));

- Type-safety and Typescript autocompletion on the properties you try to sort
- Define nested property to sort on using a path string like: `"author.name"`
- Supports sorting by `string`, `number`, `Date`, `Symbol` and `BigInt` values.
- Supports sorting by `string`, `number`, `boolean`, `Date`, `Symbol` and `BigInt` values.
- Handles `null` and `undefined` values gracefully by moving the object to the end of the array.
- High performance, up to 3 times faster than lodash orderBy and sortBy *
- High performance, up to 3 times faster than lodash orderBy and sortBy \*

Try it out: https://codesandbox.io/s/sort-by-property-example-hin358

Expand All @@ -31,16 +31,17 @@ yarn add sort-by-property
```

## Usage

```typescript
// For an array of objects
import { sortByProperty } from 'sort-by-property';

// For one-dimensional arrays
import { sortBy } from 'sort-by-property';

```

## Example: Sorting an array of objects

```typescript
import { sortByProperty } from 'sort-by-property';

Expand Down Expand Up @@ -103,6 +104,7 @@ Will show an autocomplete of the available properties to sort on:
![autocomplete](https://github.com/jvandenaardweg/typed-sort-by/blob/main/src/examples/autocomplete.png?raw=true)

## Example: Sorting one-dimensional arrays

This package exports 2 methods. Use `sortBy` to sort one-dimensional arrays. This sorting method supports all the same types as `sortByProperty`.

```typescript
Expand All @@ -115,4 +117,4 @@ array.sort(sortBy('asc'));
// Result: ['a', 'b', 'c']
```

<sub>* on an array with 10 million items: ~450ms vs ~1350ms. See the /src/examples directory.</sub>
<sub>\* on an array with 10 million items: ~450ms vs ~1350ms. See the /src/examples directory.</sub>
40 changes: 40 additions & 0 deletions src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,22 @@ describe('arrays', () => {
expect(result).toStrictEqual(expected);
});

it('should sort an array of booleans in ascending order', () => {
const unsortedArray = [true, false, true];
const result = unsortedArray.sort(sortBy('asc'));
const expected = [true, true, false];

expect(result).toStrictEqual(expected);
});

it('should sort an array of booleans as strings in descending order', () => {
const unsortedArray = [true, false, true];
const result = unsortedArray.sort(sortBy('desc'));
const expected = [false, true, true];

expect(result).toStrictEqual(expected);
});

it('should error when all array items are not from the same type while sorting descending', () => {
const unsortedArray = [1, '2', 3];
const resultFn = () => unsortedArray.sort(sortBy('desc'));
Expand Down Expand Up @@ -567,6 +583,30 @@ describe('arrays', () => {
expect(result).toStrictEqual(expected);
});

it('should sort an array of booleans in ascending order', () => {
const a = { boolean: true };
const b = { boolean: true };
const c = { boolean: false };

const unsortedArray = [b, c, a];
const result = unsortedArray.sort(sortByProperty('boolean', 'asc'));
const expected = [a, b, c];

expect(result).toStrictEqual(expected);
});

it('should sort an array of booleans in descending order', () => {
const a = { boolean: true };
const b = { boolean: true };
const c = { boolean: false };

const unsortedArray = [b, c, a];
const result = unsortedArray.sort(sortByProperty('boolean', 'desc'));
const expected = [c, b, a];

expect(result).toStrictEqual(expected);
});

it('should sort a really deeply nested object in ascending order', () => {
const a = {
user: {
Expand Down
16 changes: 16 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ export type SupportedTypes =
| number[]
| string
| string[]
| boolean
| boolean[]
| Date
| Date[]
| bigint
Expand Down Expand Up @@ -75,6 +77,13 @@ export function sortBy<T>(direction: SortByDirection): SortFunctionReturn<T> {
if (isSymbol(a) && isSymbol(b)) {
return a.toString().localeCompare(b.toString());
}

// boolean asc (true -> false)
if (isBoolean(a) && isBoolean(b)) {
if (a) return -1;
if (b) return 1;
return 0;
}
}

// number desc (b -> a)
Expand Down Expand Up @@ -121,6 +130,13 @@ export function sortBy<T>(direction: SortByDirection): SortFunctionReturn<T> {
return b.toString().localeCompare(a.toString());
}

// boolean asc (true -> false)
if (isBoolean(a) && isBoolean(b)) {
if (b) return -1;
if (a) return 1;
return 0;
}

// if a is null or undefined and b is not, a is greater than b
// moving the item to the end of the array
if (isNil(a) && b) {
Expand Down
32 changes: 32 additions & 0 deletions src/utils/boolean.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { isBoolean } from './boolean';

// an array of values that return true for isBoolean
const booleanValues = [true, false];

// an array of values that return false for isBoolean
const nonBooleanValues = [
0,
1,
2,
'0',
'1',
'2',
{},
[],
// eslint-disable-next-line @typescript-eslint/no-empty-function
() => {},
new Date(),
BigInt(0),
null,
undefined,
];

describe('isBoolean', () => {
it.each(booleanValues)('should return true for %p', value => {
expect(isBoolean(value)).toBe(true);
});

it.each(nonBooleanValues)('should return false for %p', value => {
expect(isBoolean(value)).toBe(false);
});
});
6 changes: 6 additions & 0 deletions src/utils/boolean.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* Returns whether the value passed is a boolean.
*/
export function isBoolean(value: unknown): value is boolean {
return typeof value === 'boolean';
}

0 comments on commit 29c32c9

Please sign in to comment.