Ramda: convert binary function to arbitrary arity function - ramda.js

Ramda has cool or function, which substitutes (a, b) => a || b in composition pipelines. But the point is this is binary function, that accepts only two args. I have a need of using it with any number of args, acting sort of universal || operator. (a, b, c) => a || b || c Any ideas how to implement that using ramda's toolset?

You can use or with reduce:
reduce(or, false, [0, 0, 42, 0, 1]);
//=> 42
However this wouldn't return early as in 0 || 0 || 42 || 0 || 1. Depending on your dataset this may or may not be an issue.

You can create a similar function by using R.any with R.identity, and using R.unapply to convert the arguments to an array. However, this function cannot be curried, since the number of parameters is unknown.
const { unapply, any, identity } = R
const fn = unapply(any(identity))
console.log(fn(false, false, false))
console.log(fn(false, false, true))
console.log(fn(false, false, false, true))
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js" integrity="sha512-rZHvUXcc1zWKsxm7rJ8lVQuIr1oOmm7cShlvpV0gWf0RvbcJN6x96al/Rp2L2BI4a4ZkT2/YfVe/8YvB2UHzQw==" crossorigin="anonymous"></script>
You can the same thing to emulate R.and with multiple arguments by using R.all:
const { unapply, all, identity } = R
const fn = unapply(all(identity))
console.log(fn(false, false, false))
console.log(fn(false, false, true))
console.log(fn(true, true, true, true))
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js" integrity="sha512-rZHvUXcc1zWKsxm7rJ8lVQuIr1oOmm7cShlvpV0gWf0RvbcJN6x96al/Rp2L2BI4a4ZkT2/YfVe/8YvB2UHzQw==" crossorigin="anonymous"></script>

Related

How to apply a function to multiple columns of a polars DataFrame in Rust

I'd like to apply a user-define function which takes a few inputs (corresponding some columns in a polars DataFrame) to some columns of a polars DataFrame in Rust. The pattern that I'm using is as below. I wonder is this the best practice?
fn my_filter_func(col1: &Series, col2: &Series, col2: &Series) -> ReturnType {
let it = (0..n).map(|i| {
let col1 = match col.get(i) {
AnyValue::UInt64(val) => val,
_ => panic!("Wrong type of col1!"),
};
// similar for col2 and col3
// apply user-defined function to col1, col2 and col3
}
// convert it to a collection of the required type
}
You can downcast the Series to the proper type you want to iterate over, and then use rust iterators to apply your logic.
fn my_black_box_function(a: f32, b: f32) -> f32 {
// do something
a
}
fn apply_multiples(col_a: &Series, col_b: &Series) -> Float32Chunked {
match (col_a.dtype(), col_b.dtype()) {
(DataType::Float32, DataType::Float32) => {
let a = col_a.f32().unwrap();
let b = col_b.f32().unwrap();
a.into_iter()
.zip(b.into_iter())
.map(|(opt_a, opt_b)| match (opt_a, opt_b) {
(Some(a), Some(b)) => Some(my_black_box_function(a, b)),
_ => None,
})
.collect()
}
_ => panic!("unpexptected dtypes"),
}
}
Lazy API
You don't have to leave the lazy API to be able to access my_black_box_function.
We can collect the columns we want to apply in a Struct data type and then apply a closure over that Series.
fn apply_multiples(lf: LazyFrame) -> Result<DataFrame> {
df![
"a" => [1.0, 2.0, 3.0],
"b" => [3.0, 5.1, 0.3]
]?
.lazy()
.select([concat_lst(["col_a", "col_b"]).map(
|s| {
let ca = s.struct_()?;
let b = ca.field_by_name("col_a")?;
let a = ca.field_by_name("col_b")?;
let a = a.f32()?;
let b = b.f32()?;
let out: Float32Chunked = a
.into_iter()
.zip(b.into_iter())
.map(|(opt_a, opt_b)| match (opt_a, opt_b) {
(Some(a), Some(b)) => Some(my_black_box_function(a, b)),
_ => None,
})
.collect();
Ok(out.into_series())
},
GetOutput::from_type(DataType::Float32),
)])
.collect()
}
The solution I found working for me is with map_multiple(my understanding - this to be used if no groupby/agg) or apply_multiple(my understanding - whenerver you have groupby/agg). Alternatively, you could also use map_many or apply_many. See below.
use polars::prelude::*;
use polars::df;
fn main() {
let df = df! [
"names" => ["a", "b", "a"],
"values" => [1, 2, 3],
"values_nulls" => [Some(1), None, Some(3)],
"new_vals" => [Some(1.0), None, Some(3.0)]
].unwrap();
println!("{:?}", df);
//df.try_apply("values_nulls", |s: &Series| s.cast(&DataType::Float64)).unwrap();
let df = df.lazy()
.groupby([col("names")])
.agg( [
total_delta_sens().sum()
]
);
println!("{:?}", df.collect());
}
pub fn total_delta_sens () -> Expr {
let s: &mut [Expr] = &mut [col("values"), col("values_nulls"), col("new_vals")];
fn sum_fa(s: &mut [Series])->Result<Series>{
let mut ss = s[0].cast(&DataType::Float64).unwrap().fill_null(FillNullStrategy::Zero).unwrap().clone();
for i in 1..s.len(){
ss = ss.add_to(&s[i].cast(&DataType::Float64).unwrap().fill_null(FillNullStrategy::Zero).unwrap()).unwrap();
}
Ok(ss)
}
let o = GetOutput::from_type(DataType::Float64);
map_multiple(sum_fa, s, o)
}
Here total_delta_sens is just a wrapper function for convenience. You don't have to use it.You can do directly this within your .agg([]) or .with_columns([]) :
lit::<f64>(0.0).map_many(sum_fa, &[col("norm"), col("uniform")], o)
Inside sum_fa you can as Richie already mentioned downcast to ChunkedArray and .iter() or even .par_iter()
Hope that helps

Multiple props in Ramda lens

Is there a way to apply transforms to multiple keys of an object in Ramda? I am aware this is achievable by R.evolve, but I am interested in knowing if this can be achieved by some modification of lenses.
E.g.:
const data = {
a: "100",
b: "non_numeric_string",
c: "0.5"
}
const numerize = x => +x
const mapping = {
a: numerize,
c: numerize
}
magicFunction(mapping, data)
output:
{
a: 100,
b: "non_numeric_string",
c: 0.5
}
The whole point of a lens is to focus on one part of a data structure. While it is not hard to write something using lensProp to achieve this, I'm don't think it's either very satisfying or a particularly appropriate use of lenses. Here's one Ramda solution:
const magicFunction = (mapping, data) =>
reduce
( (o, [k, fn]) => over (lensProp(k), fn, o)
, data
, toPairs (mapping)
)
const numerize = x => Number (x)
const mapping = {
a: numerize,
c: numerize
}
const data = {a: "100", b: "non_numeric_string", c: "0.5"}
console .log (
magicFunction (mapping, data)
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script> const { lensProp, over, reduce, toPairs } = R </script>
But note that a plain ES6 function does the job just as simply, without using lenses:
const magicFunction = (mapping, data) =>
Object.entries (mapping). reduce
( (o, [k, fn]) => ({...o, [k]: fn (o [k]) })
, data
)
Lenses simply don't gain you much here.

how to iterate through two arrays simultaneously with lodash

I have
A = [1,2,3,4,5,6,7]
B = [3,5,9]
I want to get an array C containing the last elements < than elements in B, like
C = [2,4,7], by using Lodash
I tried
C=_.map(A, a = (v) -> v == _.findLast(A, b = (v) -> v < _.forEach(B, c = (v) -> v==v)))
which does not work. Above I used coffeescript instead of javascript, but please reply with either, I want a solution using lodash, without explicit looping through B elements, thank you.
The forEach is redundant, and just returns the original collection:
const A = [1,2,3,4,5,6,7]
const B = [3,5,9]
// C = [2,4,7], by using Lodash
const result = _.map(B, n => _.findLast(A, m => m < n));
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
I know you said you want a lodash soultion, but just in case you were curious here is a way to get your desired array using vanilla ES6:
const A = [1, 2, 3, 4, 5, 6, 7];
const B = [3, 5, 9];
const C = findEls(A, B);
function findEls(A, B) {
const copy = [...A].reverse(); //Copy since reverse is an in-place operation
return B.map(b => {
return copy.find(a => a < b);
});
}
console.log(C);

Validating a non-empty String in Lo-Dash [duplicate]

Is there a string.Empty in JavaScript, or is it just a case of checking for ""?
Empty string, undefined, null, ...
To check for a truthy value:
if (strValue) {
// strValue was non-empty string, true, 42, Infinity, [], ...
}
To check for a falsy value:
if (!strValue) {
// strValue was empty string, false, 0, null, undefined, ...
}
Empty string (only!)
To check for exactly an empty string, compare for strict equality against "" using the === operator:
if (strValue === "") {
// strValue was empty string
}
To check for not an empty string strictly, use the !== operator:
if (strValue !== "") {
// strValue was not an empty string
}
For checking if a variable is falsey or if it has length attribute equal to zero (which for a string, means it is empty), I use:
function isEmpty(str) {
return (!str || str.length === 0 );
}
(Note that strings aren't the only variables with a length attribute, arrays have them as well, for example.)
Alternativaly, you can use the (not so) newly optional chaining and arrow functions to simplify:
const isEmpty = (str) => (!str?.length);
It will check the length, returning undefined in case of a nullish value, without throwing an error. In the case of an empty value, zero is falsy and the result is still valid.
For checking if a variable is falsey or if the string only contains whitespace or is empty, I use:
function isBlank(str) {
return (!str || /^\s*$/.test(str));
}
If you want, you can monkey-patch the String prototype like this:
String.prototype.isEmpty = function() {
// This doesn't work the same way as the isEmpty function used
// in the first example, it will return true for strings containing only whitespace
return (this.length === 0 || !this.trim());
};
console.log("example".isEmpty());
Note that monkey-patching built-in types are controversial, as it can break code that depends on the existing structure of built-in types, for whatever reason.
All the previous answers are good, but this will be even better. Use dual NOT operators (!!):
if (!!str) {
// Some code here
}
Or use type casting:
if (Boolean(str)) {
// Code here
}
Both do the same function. Typecast the variable to Boolean, where str is a variable.
It returns false for null, undefined, 0, 000, "", false.
It returns true for all string values other than the empty string (including strings like "0" and " ")
The closest thing you can get to str.Empty (with the precondition that str is a String) is:
if (!str.length) { ...
If you need to make sure that the string is not just a bunch of empty spaces (I'm assuming this is for form validation) you need to do a replace on the spaces.
if(str.replace(/\s/g,"") == ""){
}
I use:
function empty(e) {
switch (e) {
case "":
case 0:
case "0":
case null:
case false:
case undefined:
return true;
default:
return false;
}
}
empty(null) // true
empty(0) // true
empty(7) // false
empty("") // true
empty((function() {
return ""
})) // false
Performance
I perform tests on macOS v10.13.6 (High Sierra) for 18 chosen solutions. Solutions works slightly different (for corner-case input data) which was presented in the snippet below.
Conclusions
the simple solutions based on !str,==,=== and length are fast for all browsers (A,B,C,G,I,J)
the solutions based on the regular expression (test,replace) and charAt are slowest for all browsers (H,L,M,P)
the solutions marked as fastest was fastest only for one test run - but in many runs it changes inside 'fast' solutions group
Details
In the below snippet I compare results of chosen 18 methods by use different input parameters
"" "a" " "- empty string, string with letter and string with space
[] {} f- array, object and function
0 1 NaN Infinity - numbers
true false - Boolean
null undefined
Not all tested methods support all input cases.
function A(str) {
let r=1;
if (!str)
r=0;
return r;
}
function B(str) {
let r=1;
if (str == "")
r=0;
return r;
}
function C(str) {
let r=1;
if (str === "")
r=0;
return r;
}
function D(str) {
let r=1;
if(!str || 0 === str.length)
r=0;
return r;
}
function E(str) {
let r=1;
if(!str || /^\s*$/.test(str))
r=0;
return r;
}
function F(str) {
let r=1;
if(!Boolean(str))
r=0;
return r;
}
function G(str) {
let r=1;
if(! ((typeof str != 'undefined') && str) )
r=0;
return r;
}
function H(str) {
let r=1;
if(!/\S/.test(str))
r=0;
return r;
}
function I(str) {
let r=1;
if (!str.length)
r=0;
return r;
}
function J(str) {
let r=1;
if(str.length <= 0)
r=0;
return r;
}
function K(str) {
let r=1;
if(str.length === 0 || !str.trim())
r=0;
return r;
}
function L(str) {
let r=1;
if ( str.replace(/\s/g,"") == "")
r=0;
return r;
}
function M(str) {
let r=1;
if((/^\s*$/).test(str))
r=0;
return r;
}
function N(str) {
let r=1;
if(!str || !str.trim().length)
r=0;
return r;
}
function O(str) {
let r=1;
if(!str || !str.trim())
r=0;
return r;
}
function P(str) {
let r=1;
if(!str.charAt(0))
r=0;
return r;
}
function Q(str) {
let r=1;
if(!str || (str.trim()==''))
r=0;
return r;
}
function R(str) {
let r=1;
if (typeof str == 'undefined' ||
!str ||
str.length === 0 ||
str === "" ||
!/[^\s]/.test(str) ||
/^\s*$/.test(str) ||
str.replace(/\s/g,"") === "")
r=0;
return r;
}
// --- TEST ---
console.log( ' "" "a" " " [] {} 0 1 NaN Infinity f true false null undefined ');
let log1 = (s,f)=> console.log(`${s}: ${f("")} ${f("a")} ${f(" ")} ${f([])} ${f({})} ${f(0)} ${f(1)} ${f(NaN)} ${f(Infinity)} ${f(f)} ${f(true)} ${f(false)} ${f(null)} ${f(undefined)}`);
let log2 = (s,f)=> console.log(`${s}: ${f("")} ${f("a")} ${f(" ")} ${f([])} ${f({})} ${f(0)} ${f(1)} ${f(NaN)} ${f(Infinity)} ${f(f)} ${f(true)} ${f(false)}`);
let log3 = (s,f)=> console.log(`${s}: ${f("")} ${f("a")} ${f(" ")}`);
log1('A', A);
log1('B', B);
log1('C', C);
log1('D', D);
log1('E', E);
log1('F', F);
log1('G', G);
log1('H', H);
log2('I', I);
log2('J', J);
log3('K', K);
log3('L', L);
log3('M', M);
log3('N', N);
log3('O', O);
log3('P', P);
log3('Q', Q);
log3('R', R);
And then for all methods I perform speed test case str = "" for browsers Chrome v78.0.0, Safari v13.0.4, and Firefox v71.0.0 - you can run tests on your machine here
You can use lodash:
_.isEmpty(value).
It covers a lot of cases like {}, '', null, undefined, etc.
But it always returns true for Number type of JavaScript primitive data types like _.isEmpty(10) or _.isEmpty(Number.MAX_VALUE) both returns true.
Very generic "All-In-One" Function (not recommended though):
function is_empty(x)
{
return ( //don't put newline after return
(typeof x == 'undefined')
||
(x == null)
||
(x == false) //same as: !x
||
(x.length == 0)
||
(x == 0) // note this line, you might not need this.
||
(x == "")
||
(x.replace(/\s/g,"") == "")
||
(!/[^\s]/.test(x))
||
(/^\s*$/.test(x))
);
}
However, I don't recommend to use that, because your target variable should be of specific type (i.e. string, or numeric, or object?), so apply the checks that are relative to that variable.
var s; // undefined
var s = ""; // ""
s.length // 0
There's nothing representing an empty string in JavaScript. Do a check against either length (if you know that the var will always be a string) or against ""
Try:
if (str && str.trim().length) {
//...
}
I would not worry too much about the most efficient method. Use what is most clear to your intention. For me that's usually strVar == "".
As per the comment from Constantin, if strVar could some how end up containing an integer 0 value, then that would indeed be one of those intention-clarifying situations.
A lot of answers, and a lot of different possibilities!
Without a doubt for quick and simple implementation the winner is: if (!str.length) {...}
However, as many other examples are available. The best functional method to go about this, I would suggest:
function empty(str)
{
if (typeof str == 'undefined' || !str || str.length === 0 || str === "" || !/[^\s]/.test(str) || /^\s*$/.test(str) || str.replace(/\s/g,"") === "")
return true;
else
return false;
}
A bit excessive, I know.
check that var a; exist
trim out the false spaces in the value, then test for emptiness
if ((a)&&(a.trim()!=''))
{
// if variable a is not empty do this
}
You could also go with regular expressions:
if((/^\s*$/).test(str)) { }
Checks for strings that are either empty or filled with whitespace.
I usually use something like this,
if (!str.length) {
// Do something
}
Also, in case you consider a whitespace filled string as "empty".
You can test it with this regular expression:
!/\S/.test(string); // Returns true if blank.
If one needs to detect not only empty but also blank strings, I'll add to Goral's answer:
function isEmpty(s){
return !s.length;
}
function isBlank(s){
return isEmpty(s.trim());
}
if ((str?.trim()?.length || 0) > 0) {
// str must not be any of:
// undefined
// null
// ""
// " " or just whitespace
}
Or in function form:
const isNotNilOrWhitespace = input => (input?.trim()?.length || 0) > 0;
const isNilOrWhitespace = input => (input?.trim()?.length || 0) === 0;
Starting with:
return (!value || value == undefined || value == "" || value.length == 0);
Looking at the last condition, if value == "", its length must be 0. Therefore drop it:
return (!value || value == undefined || value == "");
But wait! In JavaScript, an empty string is false. Therefore, drop value == "":
return (!value || value == undefined);
And !undefined is true, so that check isn't needed. So we have:
return (!value);
And we don't need parentheses:
return !value
I use a combination, and the fastest checks are first.
function isBlank(pString) {
if (!pString) {
return true;
}
// Checks for a non-white space character
// which I think [citation needed] is faster
// than removing all the whitespace and checking
// against an empty string
return !/[^\s]+/.test(pString);
}
I have not noticed an answer that takes into account the possibility of null characters in a string. For example, if we have a null character string:
var y = "\0"; // an empty string, but has a null character
(y === "") // false, testing against an empty string does not work
(y.length === 0) // false
(y) // true, this is also not expected
(y.match(/^[\s]*$/)) // false, again not wanted
To test its nullness one could do something like this:
String.prototype.isNull = function(){
return Boolean(this.match(/^[\0]*$/));
}
...
"\0".isNull() // true
It works on a null string, and on an empty string and it is accessible for all strings. In addition, it could be expanded to contain other JavaScript empty or whitespace characters (i.e. nonbreaking space, byte order mark, line/paragraph separator, etc.).
Meanwhile we can have one function that checks for all 'empties' like null, undefined, '', ' ', {}, [].
So I just wrote this.
var isEmpty = function(data) {
if(typeof(data) === 'object'){
if(JSON.stringify(data) === '{}' || JSON.stringify(data) === '[]'){
return true;
}else if(!data){
return true;
}
return false;
}else if(typeof(data) === 'string'){
if(!data.trim()){
return true;
}
return false;
}else if(typeof(data) === 'undefined'){
return true;
}else{
return false;
}
}
Use cases and results.
console.log(isEmpty()); // true
console.log(isEmpty(null)); // true
console.log(isEmpty('')); // true
console.log(isEmpty(' ')); // true
console.log(isEmpty(undefined)); // true
console.log(isEmpty({})); // true
console.log(isEmpty([])); // true
console.log(isEmpty(0)); // false
console.log(isEmpty('Hey')); // false
I did some research on what happens if you pass a non-string and non-empty/null value to a tester function. As many know, (0 == "") is true in JavaScript, but since 0 is a value and not empty or null, you may want to test for it.
The following two functions return true only for undefined, null, empty/whitespace values and false for everything else, such as numbers, Boolean, objects, expressions, etc.
function IsNullOrEmpty(value)
{
return (value == null || value === "");
}
function IsNullOrWhiteSpace(value)
{
return (value == null || !/\S/.test(value));
}
More complicated examples exists, but these are simple and give consistent results. There is no need to test for undefined, since it's included in (value == null) check. You may also mimic C# behaviour by adding them to String like this:
String.IsNullOrEmpty = function (value) { ... }
You do not want to put it in Strings prototype, because if the instance of the String-class is null, it will error:
String.prototype.IsNullOrEmpty = function (value) { ... }
var myvar = null;
if (1 == 2) { myvar = "OK"; } // Could be set
myvar.IsNullOrEmpty(); // Throws error
I tested with the following value array. You can loop it through to test your functions if in doubt.
// Helper items
var MyClass = function (b) { this.a = "Hello World!"; this.b = b; };
MyClass.prototype.hello = function () { if (this.b == null) { alert(this.a); } else { alert(this.b); } };
var z;
var arr = [
// 0: Explanation for printing, 1: actual value
['undefined', undefined],
['(var) z', z],
['null', null],
['empty', ''],
['space', ' '],
['tab', '\t'],
['newline', '\n'],
['carriage return', '\r'],
['"\\r\\n"', '\r\n'],
['"\\n\\r"', '\n\r'],
['" \\t \\n "', ' \t \n '],
['" txt \\t test \\n"', ' txt \t test \n'],
['"txt"', "txt"],
['"undefined"', 'undefined'],
['"null"', 'null'],
['"0"', '0'],
['"1"', '1'],
['"1.5"', '1.5'],
['"1,5"', '1,5'], // Valid number in some locales, not in JavaScript
['comma', ','],
['dot', '.'],
['".5"', '.5'],
['0', 0],
['0.0', 0.0],
['1', 1],
['1.5', 1.5],
['NaN', NaN],
['/\S/', /\S/],
['true', true],
['false', false],
['function, returns true', function () { return true; } ],
['function, returns false', function () { return false; } ],
['function, returns null', function () { return null; } ],
['function, returns string', function () { return "test"; } ],
['function, returns undefined', function () { } ],
['MyClass', MyClass],
['new MyClass', new MyClass()],
['empty object', {}],
['non-empty object', { a: "a", match: "bogus", test: "bogus"}],
['object with toString: string', { a: "a", match: "bogus", test: "bogus", toString: function () { return "test"; } }],
['object with toString: null', { a: "a", match: "bogus", test: "bogus", toString: function () { return null; } }]
];
I didn't see a good answer here (at least not an answer that fits for me)
So I decided to answer myself:
value === undefined || value === null || value === "";
You need to start checking if it's undefined. Otherwise your method can explode, and then you can check if it equals null or is equal to an empty string.
You cannot have !! or only if(value) since if you check 0 it's going to give you a false answer (0 is false).
With that said, wrap it up in a method like:
public static isEmpty(value: any): boolean {
return value === undefined || value === null || value === "";
}
PS.: You don't need to check typeof, since it would explode and throw even before it enters the method
Trimming whitespace with the null-coalescing operator:
if (!str?.trim()) {
// do something...
}
There is a lot of useful information here, but in my opinion, one of the most important elements was not addressed.
null, undefined, and "" are all falsy.
When evaluating for an empty string, it's often because you need to replace it with something else.
In which case, you can expect the following behavior.
var a = ""
var b = null
var c = undefined
console.log(a || "falsy string provided") // prints ->"falsy string provided"
console.log(b || "falsy string provided") // prints ->"falsy string provided"
console.log(c || "falsy string provided") // prints ->"falsy string provided"
With that in mind, a method or function that can return whether or not a string is "", null, or undefined (an invalid string) versus a valid string is as simple as this:
const validStr = (str) => str ? true : false
validStr(undefined) // returns false
validStr(null) // returns false
validStr("") // returns false
validStr("My String") // returns true
Try this:
export const isEmpty = string => (!string || !string.length);
All these answers are nice.
But I cannot be sure that variable is a string, doesn't contain only spaces (this is important for me), and can contain '0' (string).
My version:
function empty(str){
return !str || !/[^\s]+/.test(str);
}
empty(null); // true
empty(0); // true
empty(7); // false
empty(""); // true
empty("0"); // false
empty(" "); // true
Sample on jsfiddle.
There's no isEmpty() method, you have to check for the type and the length:
if (typeof test === 'string' && test.length === 0){
...
The type check is needed in order to avoid runtime errors when test is undefined or null.

Is there a consistent way to test for undefined and null in typescript 2.0? [duplicate]

Since TypeScript is strongly-typed, simply using if () {} to check for null and undefined doesn't sound right.
Does TypeScript have any dedicated function or syntax sugar for this?
Using a juggling-check, you can test both null and undefined in one hit:
if (x == null) {
If you use a strict-check, it will only be true for values set to null and won't evaluate as true for undefined variables:
if (x === null) {
You can try this with various values using this example:
var a: number;
var b: number = null;
function check(x, name) {
if (x == null) {
console.log(name + ' == null');
}
if (x === null) {
console.log(name + ' === null');
}
if (typeof x === 'undefined') {
console.log(name + ' is undefined');
}
}
check(a, 'a');
check(b, 'b');
Output
"a == null"
"a is undefined"
"b == null"
"b === null"
if( value ) {
}
will evaluate to true if value is not:
null
undefined
NaN
empty string ''
0
false
typescript includes javascript rules.
In TypeScript 3.7 we have now Optional chaining and Nullish Coalescing to check null and undefined in the same time, example:
let x = foo?.bar.baz();
this code will check if foo is defined otherwise it will return undefined
old way :
if(foo != null && foo != undefined) {
x = foo.bar.baz();
}
this:
let x = (foo === null || foo === undefined) ? undefined : foo.bar();
if (foo && foo.bar && foo.bar.baz) { // ... }
With optional chaining will be:
let x = foo?.bar();
if (foo?.bar?.baz) { // ... }
another new feature is Nullish Coalescing, example:
let x = foo ?? bar(); // return foo if it's not null or undefined otherwise calculate bar
old way:
let x = (foo !== null && foo !== undefined) ?
foo :
bar();
BONUS
Does TypeScript has dedicated function or syntax sugar for this
TypeScript fully understands the JavaScript version which is something == null.
TypeScript will correctly rule out both null and undefined with such checks.
More
https://basarat.gitbook.io/typescript/recap/null-undefined
I did different tests on the typescript playground:
http://www.typescriptlang.org/play/
let a;
let b = null;
let c = "";
var output = "";
if (a == null) output += "a is null or undefined\n";
if (b == null) output += "b is null or undefined\n";
if (c == null) output += "c is null or undefined\n";
if (a != null) output += "a is defined\n";
if (b != null) output += "b is defined\n";
if (c != null) output += "c is defined\n";
if (a) output += "a is defined (2nd method)\n";
if (b) output += "b is defined (2nd method)\n";
if (c) output += "c is defined (2nd method)\n";
console.log(output);
gives:
a is null or undefined
b is null or undefined
c is defined
so:
checking if (a == null) is right to know if a is null or undefined
checking if (a != null) is right to know if a is defined
checking if (a) is wrong to know if a is defined
You may want to try
if(!!someValue)
with !!.
Explanation
The first ! will turn your expression into a boolean value.
Then !someValue is true if someValue is falsy and false if someValue is truthy. This might be confusing.
By adding another !, the expression is now true if someValue is truthy and false if someValue is falsy, which is much easier to manage.
Discussion
Now, why do I bother myself with if (!!someValue) when something like if (someValue) would have give me the same result?
Because !!someValue is precisely a boolean expression, whereas someValue could be absolutely anything. This kind of expression will now alow to write functions (and God we need those) like:
isSomeValueDefined(): boolean {
return !!someValue
}
instead of:
isSomeValueDefined(): boolean {
if(someValue) {
return true
}
return false
}
I hope it helps.
For Typescript 2.x.x you should do it in a following way(using type guard):
tl;dr
function isDefined<T>(value: T | undefined | null): value is T {
return <T>value !== undefined && <T>value !== null;
}
Why?
In this way isDefined() will respect variable's type and the following code would know take this check in account.
Example 1 - basic check:
function getFoo(foo: string): void {
//
}
function getBar(bar: string| undefined) {
getFoo(bar); //ERROR: "bar" can be undefined
if (isDefined(bar)) {
getFoo(bar); // Ok now, typescript knows that "bar' is defined
}
}
Example 2 - types respect:
function getFoo(foo: string): void {
//
}
function getBar(bar: number | undefined) {
getFoo(bar); // ERROR: "number | undefined" is not assignable to "string"
if (isDefined(bar)) {
getFoo(bar); // ERROR: "number" is not assignable to "string", but it's ok - we know it's number
}
}
I think this answer needs an update, check the edit history for the old answer.
Basically, you have three deferent cases null, undefined, and undeclared, see the snippet below.
// bad-file.ts
console.log(message)
You'll get an error says that variable message is undefined (aka undeclared), of course, the Typescript compiler shouldn't let you do that but REALLY nothing can prevent you.
// evil-file.ts
// #ts-gnore
console.log(message)
The compiler will be happy to just compile the code above.
So, if you're sure that all variables are declared you can simply do that
if ( message != null ) {
// do something with the message
}
the code above will check for null and undefined, BUT in case the message variable may be undeclared (for safety), you may consider the following code
if ( typeof(message) !== 'undefined' && message !== null ) {
// message variable is more than safe to be used.
}
Note: the order here typeof(message) !== 'undefined' && message !== null is very important you have to check for the undefined state first atherwise it will be just the same as message != null, thanks #Jaider.
SIMPLE ANSWER
Although Typescript is a strongly typed language, it has the same problems with pointers and variables initialization inherited from Javascript.
Javascript doesn't check whether a variable exists in the context, the so common undefined status.
to evaluate if value ISN'T null,undefined,0,false,"", or NaN:
if ( value )
or
if ( !!value )
for negative conditional, check if the value is null,undefined,0,false,"",or NaN:
if ( !value )
to test if is null or undefined:
if ( value == null )
to test only null:
if ( value === null )
to test only undefined:
if ( value === undefined )
MORE DETAILED ANSWER
1- It will evaluate to true if value is not: null, undefined, NaN, empty string '', 0, false
If the value is null,undefined,NaN,empty string,0, or false, will go to the else condition.
if ( value ) {
console.log('value is something different from 0, "", false, NaN, null, undefined');
} else {
console.log('value is 0, "", false, NaN, null or undefined');
}
if ( !!value ) {
console.log('value is something different from 0, "", false, NaN, null, undefined');
} else {
console.log('value is 0, "", false, NaN, null or undefined');
}
2- If you want a negative condition, then you'll need to use:
if ( !value ) {
console.log('value is 0, "", false, NaN, null or undefined');
} else {
console.log('value is something different from 0, "", false, NaN, null, undefined');
}
3- It will evaluate if value is null or undefined
if ( value == null ) {
console.log('is null or undefined');
} else {
console.log('it isnt null neither undefined');
}
4- Using a test with boolean values doesn't work.
It will NOT evaluate to true neither to false if value is null, undefined, 0, empty string, NaN
Both conditions will always go to the else condition.
With the exception if value is a boolean variable.
if ( value==true ) {
} else {
}
if ( value==false ) {
} else {
}
if(data){}
it's mean !data
null
undefined
false
....
If you want to pass tslint without setting strict-boolean-expressions to allow-null-union or allow-undefined-union, you need to use isNullOrUndefined from node's util module or roll your own:
// tslint:disable:no-null-keyword
export const isNullOrUndefined =
<T>(obj: T | null | undefined): obj is null | undefined => {
return typeof obj === "undefined" || obj === null;
};
// tslint:enable:no-null-keyword
Not exactly syntactic sugar but useful when your tslint rules are strict.
UPDATE (Sept 4, 2020)
You can now use the ?? operator to validate null and undefined "values" and set a default value. For example:
const foo = null;
const bar = foo ?? 'exampleValue';
console.log(bar); // This will print 'exampleValue' due to the value condition of the foo constant, in this case, a null value
As a verbose way, if you want to compare null and undefined values ONLY, use the following example code for reference:
const incomingValue : string = undefined;
const somethingToCompare : string = incomingValue; // If the line above is not declared, TypeScript will return an excepion
if (somethingToCompare == (undefined || null)) {
console.log(`Incoming value is: ${somethingToCompare}`);
}
If incomingValue is not declared, TypeScript should return an exception. If this is declared but not defined, the console.log() will return "Incoming value is: undefined". Note we are not using the strict equals operator.
The "correct" way (check the other answers for details), if the incomingValue is not a boolean type, just evaluate if its value is true, this will be evaluated according to the constant/variable type. A true string have to be defined explicitly as string using the = '' assignation. If not, it will be evaluated as false. Let's check this case using the same context:
const incomingValue : string = undefined;
const somethingToCompare0 : string = 'Trumpet';
const somethingToCompare1 : string = incomingValue;
if (somethingToCompare0) {
console.log(`somethingToCompare0 is: ${somethingToCompare0}`); // Will return "somethingToCompare0 is: Trumpet"
}
// Now, we will evaluate the second constant
if (somethingToCompare1) {
console.log(`somethingToCompare1 is: ${somethingToCompare1}`); // Launched if incomingValue is defined
} else {
console.log(`somethingToCompare1 is: ${somethingToCompare1}`); // Launched if incomingValue is undefined. Will return "somethingToCompare1 is: undefined"
}
If you are using TypeScript, it is a better approach to let the compiler check for nulls and undefineds (or the possibility thereof), rather than checking for them at run-time. (If you do want to check at run-time, then as many answers indicate, just use value == null).
Use the compile option strictNullChecks to tell the compiler to choke on possible null or undefined values. If you set this option, and then there is a situation where you do want to allow null and undefined, you can define the type as Type | null | undefined.
The simplest way is to use:
import { isNullOrUndefined } from 'util';
and than:
if (!isNullOrUndefined(foo))
We use a helper hasValue that both checks for nulls/undefined and ensures via TypeScript that unnecessary checks are not performed. (The latter is similar to how TS would complain about if ("a" === undefined), since it is always false).
Using this consistently is always safe, unlike !val which matches empty strings, zero, etc. It also avoid the use of fuzzy == matching which is almost always a bad practice - no need to introduce an exception.
type NullPart<T> = T & (null | undefined);
// Ensures unnecessary checks aren't performed - only a valid call if
// value could be nullable *and* could be non-nullable
type MustBeAmbiguouslyNullable<T> = NullPart<T> extends never
? never
: NonNullable<T> extends never
? never
: T;
export function hasValue<T>(
value: MustBeAmbiguouslyNullable<T>,
): value is NonNullable<MustBeAmbiguouslyNullable<T>> {
return (value as unknown) !== undefined && (value as unknown) !== null;
}
export function hasValueFn<T, A>(
value: MustBeAmbiguouslyNullable<T>,
thenFn: (value: NonNullable<T>) => A,
): A | undefined {
// Undefined matches .? syntax result
return hasValue(value) ? thenFn(value) : undefined;
}
Late to join this thread but I find this JavaScript hack very handy in checking whether a value is undefined
if(typeof(something) === 'undefined'){
// Yes this is undefined
}
May be to late! but you can use ?? operator in typescript.
see https://mariusschulz.com/blog/nullish-coalescing-the-operator-in-typescript
You can do this easily with a ternary operator and the new nullish coalesce operator.
First: check to see if it is true using the ternary. If so return false so the if statement does not run.
Second: because you now know the value is falsey, you can use the nullish coalesce operator to return true if it is nullish. Since it will return itself for any other value, if it is not nullish it will fail the if statement correctly.
let x = true;
console.log("starting tests")
if (x?false:x ?? true){
console.log(x,"is nullish")
}
x = false
if (x?false:x ?? true){
console.log(x,"is nullish")
}
x = 0;
if (x?false:x ?? true){
console.log(x,"is nullish")
}
x=1;
if (x?false:x ?? true){
console.log(x,"is nullish")
}
x="";
if (x?false:x ?? true){
console.log(x,"is nullish")
}
x="hello world";
if (x?false:x ?? true){
console.log(x,"is nullish")
}
x=null;
if (x?false:x ?? true){
console.log(x,"is nullish")
}
x=undefined;
if (x?false:x ?? true){
console.log(x,"is nullish")
}
you can use
if(x === undefined)
All,
The answer with the most votes, does not really work if you are working with an object. In that case, if a property is not present, the check will not work. And that was the issue in our case: see this sample:
var x =
{ name: "Homer", LastName: "Simpson" };
var y =
{ name: "Marge"} ;
var z =
{ name: "Bart" , LastName: undefined} ;
var a =
{ name: "Lisa" , LastName: ""} ;
var hasLastNameX = x.LastName != null;
var hasLastNameY = y.LastName != null;
var hasLastNameZ = z.LastName != null;
var hasLastNameA = a.LastName != null;
alert (hasLastNameX + ' ' + hasLastNameY + ' ' + hasLastNameZ + ' ' + hasLastNameA);
var hasLastNameXX = x.LastName !== null;
var hasLastNameYY = y.LastName !== null;
var hasLastNameZZ = z.LastName !== null;
var hasLastNameAA = a.LastName !== null;
alert (hasLastNameXX + ' ' + hasLastNameYY + ' ' + hasLastNameZZ + ' ' + hasLastNameAA);
Outcome:
true , false, false , true (in case of !=)
true , true, true, true (in case of !==) => so in this sample not the correct answer
plunkr link: https://plnkr.co/edit/BJpVHD95FhKlpHp1skUE
Since TypeScript is a typed superset of ES6 JavaScript. And lodash are a library of javascript.
Using lodash to checks if value is null or undefined can be done using _.isNil().
_.isNil(value)
Arguments
value (*): The value to check.
Returns
(boolean): Returns true if value is nullish, else false.
Example
_.isNil(null);
// => true
_.isNil(void 0);
// => true
_.isNil(NaN);
// => false
Link
Lodash Docs
A faster and shorter notation for null checks can be:
value == null ? "UNDEFINED" : value
This line is equivalent to:
if(value == null) {
console.log("UNDEFINED")
} else {
console.log(value)
}
Especially when you have a lot of null check it is a nice short notation.
I had this issue and some of the answer work just fine for JS but not for TS here is the reason.
//JS
let couldBeNullOrUndefined;
if(couldBeNullOrUndefined == null) {
console.log('null OR undefined', couldBeNullOrUndefined);
} else {
console.log('Has some value', couldBeNullOrUndefined);
}
That is all good as JS has no Types
//TS
let couldBeNullOrUndefined?: string | null; // THIS NEEDS TO BE TYPED AS undefined || null || Type(string)
if(couldBeNullOrUndefined === null) { // TS should always use strict-check
console.log('null OR undefined', couldBeNullOrUndefined);
} else {
console.log('Has some value', couldBeNullOrUndefined);
}
In TS if the variable wasn't defined with null when you try to check for that null the tslint | compiler will complain.
//tslint.json
...
"triple-equals":[true],
...
let couldBeNullOrUndefined?: string; // to fix it add | null
Types of property 'couldBeNullOrUndefined' are incompatible.
Type 'string | null' is not assignable to type 'string | undefined'.
Type 'null' is not assignable to type 'string | undefined'.
Usually I do the juggling-check as Fenton already discussed.
To make it more readable, you can use isNil from ramda.
import * as isNil from 'ramda/src/isNil';
totalAmount = isNil(totalAmount ) ? 0 : totalAmount ;
careful if you're using local storage, you can end up with the string undefined rather than the value undefined:
localStorage.setItem('mykey',JSON.stringify(undefined));
localStorage.getItem('mykey') === "undefined"
true
People may find this useful: https://github.com/angular/components/blob/master/src/cdk/coercion/boolean-property.spec.ts
/**
* #license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/** Coerces a data-bound value (typically a string) to a boolean. */
export function coerceBooleanProperty(value: any): boolean {
return value != null && `${value}` !== 'false';
}
import {coerceBooleanProperty} from './boolean-property';
describe('coerceBooleanProperty', () => {
it('should coerce undefined to false', () => {
expect(coerceBooleanProperty(undefined)).toBe(false);
});
it('should coerce null to false', () => {
expect(coerceBooleanProperty(null)).toBe(false);
});
it('should coerce the empty string to true', () => {
expect(coerceBooleanProperty('')).toBe(true);
});
it('should coerce zero to true', () => {
expect(coerceBooleanProperty(0)).toBe(true);
});
it('should coerce the string "false" to false', () => {
expect(coerceBooleanProperty('false')).toBe(false);
});
it('should coerce the boolean false to false', () => {
expect(coerceBooleanProperty(false)).toBe(false);
});
it('should coerce the boolean true to true', () => {
expect(coerceBooleanProperty(true)).toBe(true);
});
it('should coerce the string "true" to true', () => {
expect(coerceBooleanProperty('true')).toBe(true);
});
it('should coerce an arbitrary string to true', () => {
expect(coerceBooleanProperty('pink')).toBe(true);
});
it('should coerce an object to true', () => {
expect(coerceBooleanProperty({})).toBe(true);
});
it('should coerce an array to true', () => {
expect(coerceBooleanProperty([])).toBe(true);
});
});
You could use:
if (!!variable) {}
it equals writting
it (variable != null && variable != undefined) {}
I always write it like this:
var foo:string;
if(!foo){
foo="something";
}
This will work fine and I think it's very readable.