-
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 -1
Custom 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 = 0
This 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' -> true
Custom 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 number
Type 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' -> false
Custom 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); // false
Called 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. comparingNaN
withNaN
givesNaN
, since we cannot compare 2NaN
s)
If neigther of arguments not implemnting Symbol.compare trait - compareFn(3rd argument) will be called.
-
UndefinedBehaviorError
ifcompareFn
is not defined and neigther of arguments implements Symbol.compare trait -
UndefinedBehaviorError
ifcompareFn
is not a function -
UndefinedBehaviorError
ifcompareFn
returns 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 number
Partial equals. Same as ==(type loose comparison). You can interpretate it as "shallow" equal
-
UndefinedBehaviorError
for 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"); // true
Equals. 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;
}
}