-
Notifications
You must be signed in to change notification settings - Fork 0
02 cmp
This package only provide types and definitions.
This package introduce custom Symbol implementation in global object.
This symbol exists to compare 2 values - Self and another.
We recommend to throw UndefinedBehaviorError for uncomparable types.
This method should returns a number.
- If method returns
1(or more) -Self > another - If method returns
0-Self == another - If method returns
-1-Self < another - If method returns
NaN- arguments have same types but not comparable between each others. E.g.NaN == NaN -> false
Symbol.compare implemented for Number, String, Boolean and Date objects. You can implement this trait for any object and use it with primitives.
Built-in
(5)[Symbol.compare](3); // 5 > 3 returns 1
"qwe"[Symbol.compare]("asd"); // 'a' > 'q'. returns -1Custom implementation
class A {
constructor(private readonly value: number) {}
[Symbol.compare](this, another: unknown) {
if (typeof another === "number") {
return this.value - another;
}
throw new Error("unsupported type");
}
}
const a = new A(5);
(5)[Symbol.compare](a); // A(5) - 5 = 0This method tests for this and other values to be equal, and is used by == (with type lossenes).
NOTE: other always will be unknown. Generic T only helps when use with typescript. Perform checks on your side.
NOTE: partialEquals function uses this to binds self result.
Symbol.partialEquals implemented for Number, String, Boolean and Date objects. You can implement this trait for any object and use it with primitives.
accept other as unknown type
use function declaration for this binding if you need to use original object to compare
If you delcare a class - implement PartialEquals type
for objects - use partialEquals since it can interpretated as "shallow" equality
Built-in:
(5)[Symbol.partialEquals]("5"); // 5 == '5' -> trueCustom imeplementation
class A {
constructor(private readonly value: number) {}
[Symbol.partialEquals](this, another: unknown) {
if (typeof another === "number") {
return true;
}
throw new Error("unsupported type");
}
}
const a = new A(5);
(6)[Symbol.partialEquals](a); // A(6) always is true for numberType for equality comparisons which are equivalence relations.
other always will be unknown. Generic T only helps when use with typescript. Perform checks on your side.
built-in objects(Number, String, Boolean, Date) will throw UndefinedBehaviorError error for object with [Symbol.equals] trait implementation but returns not a boolean type
Return "boolean" type without throwing an error
Built-in
(6)[Symbol.equals]("6"); // 6 === '6' -> falseCustom implementation
import { type Eq, equals } from "@rslike/cmp";
enum BookFormat {
Paperback,
Hardback,
Ebook,
}
class Book implements Eq {
public isbn: boolean;
public format: BookFormat;
[Symbol.equals](other: Book) {
return other instanceof Book && this.isbn == other.isbn;
}
}
const book1 = new Book();
book1.isbn = true;
const book2 = new Book();
book2.isbn = true;
equals(book1, book2); // true
equals(book1, 5); // false
equals(book1, true); // falseCalled Symbol.compare to compare 2 arguments between each others and returns number.
In Most cases it returns 4 possible numeric values and can be interpretate:
- result is
>=1- first argument is more than incoming - result is
0- arguments are the same - result is
<=-1- second argument is more than incoming - result is
NaN- argument have same types but uncomparable between each other (e.g. comparingNaNwithNaNgivesNaN, since we cannot compare 2NaNs)
If neigther of arguments not implemnting Symbol.compare trait - compareFn(3rd argument) will be called.
-
UndefinedBehaviorErrorifcompareFnis not defined and neigther of arguments implements Symbol.compare trait -
UndefinedBehaviorErrorifcompareFnis not a function -
UndefinedBehaviorErrorifcompareFnreturns not a number type (e.g. string or boolean)
import { compare } from "@rslike/cmp";
compare(2, 3); // -1, 3 > 2
compare(2, {
[Symbol.compare]() {
return 500;
},
}); // 500, object returns 500
compare(2, {
[Symbol.compare]() {
return 'hello world'';
},
}); // throws undefiend behavior. Symbol.compare should return a numberPartial equals. Same as ==(type loose comparison). You can interpretate it as "shallow" equal
-
UndefinedBehaviorErrorfor a and b objects without implementation Symbol.partialEquals trait or if Symbol.partialEquals trait returns not boolean type.
import { partialEquals } from "@rslike/cmp";
partialEquals(5, "5"); // trueEquals. Same as ===(type looseness comparison).
Called [Symbol.equals] implementation for first or another argument. If neither of the arguments implements [Symbol.equals] trait then equalityFn argument will be called. Else - UndefinedBehaviorError will be throws
— UndefinedBehaviorError for a and b objects without implementation "Symbol.equals" trait
— UndefinedBehaviorError if [Symbol.equals] trait returns not boolean type.(e.g. string or number)
type for check equality. requires to implement [Symbol.equals]
Type for equality comparisons which are equivalence relations.
This means, that in addition to a == b and a != b being strict inverses, the equality must be (for all a, b and c):
reflexive: a == a;
symmetric: a == b implies b == a; and
transitive: a == b and b == c implies a == c.
This property cannot be checked by the compiler, and therefore Eq implies PartialEq, and has equality extra method.
specify that your type implements Eq.
enum BookFormat {
Paperback,
Hardback,
Ebook,
}
class Book implements Eq {
public isbn: number;
public format: BookFormat;
[Symbol.equals](another) {
return other instanceof Book && this.isbn == other.isbn;
}
}Requires to implement Symbol.compare trait
import { type Ord } from "@rslike/cmp";
class MyArr<number> implements Ord {
readonly currentIndex: number;
[Symbol.compare](other: number) {
return this.currentIndex - other;
}
}