src/predicates/isEqualTo.ts
import { TinyType } from '../TinyType';
import { Predicate } from './Predicate';
export function isEqualTo(expectedValue: TinyType): Predicate<TinyType>;
export function isEqualTo<T>(expectedValue: T): Predicate<T>;
/**
* @desc Ensures that the `value` is equal to `expectedValue`.
* This {@link Predicate} is typically used in combination with other {@link Predicate}s.
*
* @example <caption>Comparing Tiny Types</caption>
* import { ensure, isEqualTo, TinyType, TinyTypeOf } from 'tiny-types';
*
* class AccountId extends TinyTypeOf<number>() {}
* class Command extends TinyTypeOf<AccountId>() {}
* class UpgradeAccount extends Command {}
*
* class AccountsService {
* constructor(public readonly loggedInUser: AccountId) {}
* handle(command: Command) {
* ensure('AccountId', command.value, isEqualTo(this.loggedInUser));
* }
* }
*
* @example <caption>Comparing primitives</caption>
* import { ensure, isEqualTo, TinyType } from 'tiny-types';
*
* class Admin extends TinyType {
* constructor(public readonly id: number) {
* ensure('Admin::id', id, isEqualTo(1));
* }
* }
*
* @param {string | number | symbol | TinyType | object} expectedValue
* @returns {Predicate<any>}
*/
export function isEqualTo<T>(expectedValue: T): Predicate<T> {
return Predicate.to(`be equal to ${ String(expectedValue) }`, (value: any) =>
(hasEquals(value) && hasEquals(expectedValue))
? value.equals(expectedValue)
: value === expectedValue,
);
}
function hasEquals(value: unknown): value is { equals: (another: any) => boolean } {
return !! value && (value instanceof TinyType || (value as any).equals);
}