Skip to content

Commit

Permalink
Update: min, max, minBy, maxBy (#65)
Browse files Browse the repository at this point in the history
  • Loading branch information
Harris-Miller authored Jan 3, 2024
1 parent dc12325 commit 5413dd2
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 10 deletions.
22 changes: 22 additions & 0 deletions test/max.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { expectError, expectType } from 'tsd';

import { max } from '../es';

// please note how literals work in this situation
expectType<1 | 2>(max(1, 2));
// using variables that are type `number` is the more general use-case here
const a: number = 1;
const b: number = 2;
expectType<number>(max(a, b));
// you can also upcast inline to get the same result
expectType<number>(max(1 as number, 2 as number));
// now check the other Ord types
expectType<string>(max('a' as string, 'b' as string));
expectType<boolean>(max(true as boolean, false as boolean));
expectType<Date>(max(new Date(Date.now() - 1), new Date(Date.now())));

// curried
expectType<(b: number) => number>(max(a));

// don't allow different types
expectError(max(1, '2'));
34 changes: 34 additions & 0 deletions test/maxBy.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { expectError, expectType } from 'tsd';

import { __, maxBy, prop } from '../es';

type Obj = {
str: string;
date: Date;
bool: boolean;
};

// please note how literals work in this situation
expectType<1 | 2>(maxBy(Math.abs, 1, 2));
// using variables that are type `number` is the more general use-case here
const a: number = 1;
const b: number = 2;
expectType<number>(maxBy(Math.abs, a, b));
// you can also upcast inline to get the same result
expectType<number>(maxBy(Math.abs, 1 as number, 2 as number));
// now check the other Ord types
expectType<Obj>(maxBy(prop('str'), {} as Obj, {} as Obj));
expectType<Obj>(maxBy(prop('bool'), {} as Obj, {} as Obj));
expectType<Obj>(maxBy(prop('date'), {} as Obj, {} as Obj));

// Placeholder
// expectType<number>(max(__, a, b)(fn));
expectType<number>(maxBy(__, 1 as number, 2 as number)(Math.abs));
// curried
// notice how literals work fine here because `T` is pulled directly from Math.abs
// in the full function typescript will hard union them, but here it cannot
expectType<number>(maxBy(Math.abs)(1)(2));
expectType<number>(maxBy(Math.abs)(1, 2));

// don't allow different types
expectError(maxBy(Math.abs, 1, '2'));
22 changes: 22 additions & 0 deletions test/min.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { expectError, expectType } from 'tsd';

import { min } from '../es';

// please note how literals work in this situation
expectType<1 | 2>(min(1, 2));
// using variables that are type `number` is the more general use-case here
const a: number = 1;
const b: number = 2;
expectType<number>(min(a, b));
// you can also upcast inline to get the same result
expectType<number>(min(1 as number, 2 as number));
// now check the other Ord types
expectType<string>(min('a' as string, 'b' as string));
expectType<boolean>(min(true as boolean, false as boolean));
expectType<Date>(min(new Date(Date.now() - 1), new Date(Date.now())));

// curried
expectType<(b: number) => number>(min(a));

// don't allow different types
expectError(min(1, '2'));
34 changes: 34 additions & 0 deletions test/minBy.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { expectError, expectType } from 'tsd';

import { __, minBy, prop } from '../es';

type Obj = {
str: string;
date: Date;
bool: boolean;
};

// please note how literals work in this situation
expectType<1 | 2>(minBy(Math.abs, 1, 2));
// using variables that are type `number` is the more general use-case here
const a: number = 1;
const b: number = 2;
expectType<number>(minBy(Math.abs, a, b));
// you can also upcast inline to get the same result
expectType<number>(minBy(Math.abs, 1 as number, 2 as number));
// now check the other Ord types
expectType<Obj>(minBy(prop('str'), {} as Obj, {} as Obj));
expectType<Obj>(minBy(prop('bool'), {} as Obj, {} as Obj));
expectType<Obj>(minBy(prop('date'), {} as Obj, {} as Obj));

// Placeholder
// expectType<number>(max(__, b)(a));
expectType<number>(minBy(__, 1 as number, 2 as number)(Math.abs));
// curried
// notice how literals work fine here because `T` is pulled directly from Math.abs
// in the full function typescript will hard union them, but here it cannot
expectType<number>(minBy(Math.abs)(1)(2));
expectType<number>(minBy(Math.abs)(1, 2));

// don't allow different types
expectError(minBy(Math.abs, 1, '2'));
29 changes: 24 additions & 5 deletions types/maxBy.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,25 @@
import * as _ from 'ts-toolbelt';
import { Ord } from './util/tools';
import { Placeholder, Ord } from './util/tools';

export function maxBy<T>(keyFn: (a: T) => Ord): _.F.Curry<(a: T, b: T) => T>;
export function maxBy<T>(keyFn: (a: T) => Ord, a: T): (b: T) => T;
export function maxBy<T>(keyFn: (a: T) => Ord, a: T, b: T): T;
// Commutative means we can simplify the overloads for handlings placeholders
// maxBy(fn)
export function maxBy<T>(fn: (a: T) => Ord): {
// maxBy(fn)(a)(b)
(a: T): (b: T) => T;
// maxBy(fn)(a, b)
(a: T, b: T): T;
};
// maxBy(__, a)
export function maxBy<T>(__: Placeholder, a: T): {
// maxBy(__, a)(fn)(b)
(fn: (a: T) => Ord): (b: T) => T;
// maxBy(__, a)(__, b)(fn)
(__: Placeholder, b: T): (fn: (a: T) => Ord) => T;
// maxBy(__, a)(fn, b)
(fn: (a: T) => Ord, b: T): T;
};
// maxBy(fn, a)(b)
export function maxBy<T>(fn: (a: T) => Ord, a: T): (b: T) => T;
// maxBy(__, a, b)(fn)
export function maxBy<T>(__: Placeholder, a: T, b: T): (fn: (a: T) => Ord) => T;
// maxBy(fn, a, b)
export function maxBy<T>(fn: (a: T) => Ord, a: T, b: T): T;
29 changes: 24 additions & 5 deletions types/minBy.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,25 @@
import * as _ from 'ts-toolbelt';
import { Ord } from './util/tools';
import { Placeholder, Ord } from './util/tools';

export function minBy<T>(keyFn: (a: T) => Ord): _.F.Curry<(a: T, b: T) => T>;
export function minBy<T>(keyFn: (a: T) => Ord, a: T): (b: T) => T;
export function minBy<T>(keyFn: (a: T) => Ord, a: T, b: T): T;
// Commutative means we can simplify the overloads for handlings placeholders
// minBy(fn)
export function minBy<T>(fn: (a: T) => Ord): {
// minBy(fn)(a)(b)
(a: T): (b: T) => T;
// minBy(fn)(a, b)
(a: T, b: T): T;
};
// minBy(__, a)
export function minBy<T>(__: Placeholder, a: T): {
// minBy(__, a)(fn)(b)
(fn: (a: T) => Ord): (b: T) => T;
// minBy(__, a)(__, b)(fn)
(__: Placeholder, b: T): (fn: (a: T) => Ord) => T;
// minBy(__, a)(fn, b)
(fn: (a: T) => Ord, b: T): T;
};
// minBy(fn, a)(b)
export function minBy<T>(fn: (a: T) => Ord, a: T): (b: T) => T;
// minBy(__, a, b)(fn)
export function minBy<T>(__: Placeholder, a: T, b: T): (fn: (a: T) => Ord) => T;
// minBy(fn, a, b)
export function minBy<T>(fn: (a: T) => Ord, a: T, b: T): T;

0 comments on commit 5413dd2

Please sign in to comment.