a couple tips to help out:
- if you compare using 'string == number' javascript will convert both sides to a number, then compare
- if you compare using 'string === number' javascript will NOT convert before comparing
- "123" == 123 -> true
- "123" === 123 -> false
- new Date() == new Date() -> false
- (new Date()).getTime() == (new Date()).getTime() -> true
// odd, why is Date different?
// return (typeof (new Date())
// this gives us 'object'
// when javascript compares 2 'object'(s) it doesn't compare the contents of either object
// instead it compares each objects 'location in memory' a.k.a. 'address'
// an 'address' is just a hex number (like 0x001)
// every new object gets its own address"
// so if we make 1 new object, its address is 0x001
// now if we make another new object, its address will be 0x005
// which means: 'new Date() == new Date()' creates 2 new objects, THEN it compares
// giving you: '0x001 == 0x005' which is false
var my_date1 = new Date('2025-01-01T10:00:00Z');
var my_date2 =new Date('2025-01-01T10:00:00Z');
var my_date3 = my_date1
console.log(my_date1 == my_date2) // false
console.log(my_date1 === my_date2) // false
console.log(my_date2 == my_date3) // fase
console.log(my_date3 == my_date1) // true
console.log(my_date1.getTime() == my_date2.getTime()) // true
console.log(my_date1.getTime() === my_date2.getTime()) // true
console.log(my_date2.getTime() == my_date3.getTime()) // true
console.log(my_date3.getTime() == my_date1.getTime()) // true
var test_numbers1 = 123
var test_numbers2 = "123"
console.log(test_numbers1 == test_numbers2) // true
console.log(test_numbers1 === test_numbers2) // false
console.log(String(test_numbers1) == String(test_numbers2)) // true
console.log(test_numbers1.toString() == test_numbers2.toString()) // true
console.log(Number(test_numbers1) == Number(test_numbers2)) // true
var test_letters1 = "abcd"
var test_letters2 = "abcd"
console.log(test_letters1 == test_letters2 ) // true
console.log(test_letters1 === test_letters2 ) // false
console.log(String(test_letters1 ) == String(test_letters2 )) // true
console.log(test_letters1 .toString() == test_letters2 .toString()) // true
console.log(Number(test_letters1 ) == Number(test_letters2 )) // false
console.log(Number(test_letters1 ) === Number(test_letters2 )) // false
// these next ones can, and have, cause lots of problems when it comes to string comparison implementations
console.log(Number(test_letters1 )) // NaN
console.log(NaN == NaN) // false
// NaN is a special case in Javascript
// NaN is never equal to anything, including itself
// NaN is different from 'null' and 'undefined'
// when '==' is used, 'null' and 'undefined' are the same
// so if you have
// if ('my_expression' == null) {}
// 'my_expression' can evaluate to 'undefined' or 'null', in either case it will be true
// but if 'my_expression' evaluates to 'NaN', this if statement will never evaluate to true
var test_mixed1 = "a"
var test_mixed2 = 1
console.log(String(test_mixed1) == String(test_mixed2)) // false
console.log(Number(test_mixed1) == Number(test_mixed2)) // false
TLDR;
- if you convert values to a string as soon as they're read, then on down the road if you need to do a comparison you'll know at least 1 value will always be a string, which makes things easier since you now only have to worry about type of 1 value instead of 2.
I believe you mentioned that every column could be of any type or null, pointing out problems with mixed type comparisons:
{{ (form6[indexToUpdate].data.Price_unit_Id && ['string', 'number'].includes((typeof form6[indexToUpdate].data.Price_unit_Id).toLowerCase()))?
String(form6[indexToUpdate].data.Price_unit_Id) :
form6[indexToUpdate].data.Price_unit_Id instanceof Date?
String(form6[indexToUpdate].data.Price_uint_Id.getTime()) :
typeof form6[indexToUpdate].data.Price_unit_Id === 'object'?
JSON.stringify(form6[indexToUpdate].data.Price_unit_Id) : null }}
// Date is of type 'Object' so we can't use typeof to know what type of object
// instead we use 'instanceOf', because we want to know if the Object is a direct instance of a Date
// we know comparing .getTime() with another number works, but if you compare .getTime() to a string containing numbers, we get unexpected results
// so instead, cast .getTime() to a String (you could also use .toString() but there are a few edge cases )
// JSON objects can be tricky to compare, you either have to do some sort of depth-first traversal and comparison of all key and values
// OR
// you can cheat, turn the json object into a string and now we can compare the keys and values of 2 json object strings all at once (instead of recursive traversal)
If you know for a fact you only have Numbers, Strings and Dates (never anything else) you could simplify it
{{
(form6[indexToUpdate].data.Price_unit_Id && ['String', 'Number'].includes((typeof form6[indexToUpdate].data.Price_unit_Id)))?
String(form6[indexToUpdate].data.Price_unit_Id) :
String(form6[indexToUpdate].data.Price_uint_Id.getTime()) }}
// the 1st line tests if the key/values exist and if the value is a Number or String
// 2nd line converts all numbers and strings into a string
// 3rd line uses the rule of elimination to assume if the value isn't a number or string then it has to be a Date, so use getTime() to convert to a number and use String or .toString() to convert to a string.
you could try a more generic approach and handle Date and JSON objects the same:
{{
(form6[indexToUpdate].data.Price_unit_Id && ['String', 'Number'].includes((typeof form6[indexToUpdate].data.Price_unit_Id)))?
String(form6[indexToUpdate].data.Price_unit_Id) :
JSON.stringify(form6[indexToUpdate].data.Price_uint_Id) }}
or if you know you're only dealing with Numbers and Strings:
{{ String(form6[indexToUpdate].data.Price_unit_Id) }}
notes:
interestingly you don't necessarily need to do this to whatever value you are comparing form6[indexToUpdate].data.Price_unit_Id
to, that's because all of the above options result in a String and since this is forced we know when we compare it to some variable javascript will do what it can to convert the STRING value to a Number OR if we are comparing to an object javascript will do what it can to convert the OBJECT to a String.
if you're wondering, there are certain rules javascript follows when deciding to convert a value from one type to another when using ==
and just like PEMDAS in math these are in a specific order:
- If the types are the same, a strict comparison is performed.
- If one operand is null and the other is undefined, they are considered equal.
- If one operand is a number and the other is a string, the string is converted to a number.
- If one operand is a boolean, it is converted to a number (true becomes 1, false becomes 0).
- If one operand is an object and the other is a primitive, the object is converted to a primitive value.