filter and regex issue - javascript

I want to filter an array with a function.
if (this.pendingItems.customer?.emailAddresses) {
this.pendingItems.customer.emailAddresses.filter(email => {
isEmailValid(email);
});
}
the function isEmailValid()
export function isEmailValid(s: string): boolean {
const re =
/^[a-z0-9+-][a-z0-9_+-]*(\.[a-z0-9_+-]+)*#([a-z0-9-]+\.)+[a-z0-9-]{2,}$/i;
return re.test(s);
}
return the correct response (true or false) with the emails(test#email.com and test2email) I pass it, but the filter don't work.

You need to modify your expression slightly. The method you pass to the filter function should return true/false but it always returns void (which will be cast to false).
filter(email => isEmailValid(email))
or
filter(isEmailValid)
or
filter(email => { return isEmailValid(email) })
In case you missed it - you forgot to return the result of the isEmailValid ;)

So the solution was:
if (this.pendingItems.customer?.emailAddresses) {
this.pendingItems.customer.emailAddresses = this.pendingItems.customer.emailAddresses.filter(isEmailValid);
}
I forgot to reassign the variable ;p

Related

How to map an response when It's array and when It's not?

I just coded two simple functions to validate a field if it has a specific value, but in some cases the responses could be a array. Can I simplify these function in just one function? I tried to use the same "isOrderInLastMile" function when the response is just a object but I retrieve the "object.map is not a function" error.
function 1: I use this function when the response is an array of objects.
export function isOrderInLastMile(pieces: any): boolean {
const totalPieces: number = pieces.length;
let momentFound: number = 0;
pieces.map((element) => {
if (
element.stagesHistory &&
getCurrentMoment(element.stagesHistory) ===
MomentsLabel.En_Ășltima_milla_id
) {
momentFound = momentFound + 1;
}
return momentFound;
});
return totalPieces === momentFound;
}
Function 2: I use this function when this response is just an object
export function isPieceInLastMile(piece: any): boolean {
return (
piece.stagesHistory &&
getCurrentMoment(piece.stagesHistory) === MomentsLabel.En_Ășltima_milla_id
);
}
How Can I unify both functions? Thanks!!! :)
Either wrap your single element in an array, like this:
export function isPieceInLastMile(piece: any): boolean {
return isOrderInLastMile([piece]);
}
or use the single function in a callback
return pieces.every(isPieceInLastMile);
(The latter option can be used instead of counting all matching items)

Can't access inner function properly

Not sure if this is the right title but should be quick help.
Pretty much I keep on getting errors on testing a function because "TypeError: ParseThis.changeIt is not a function". Here's my code. What am I missing that causing this type error? Thanks!
const ParseThis = () => {
const changeIt = string => string;
return { changeIt: changeIt() }
}
Edit: More details!
Thanks for the help again
When you return your object, maybe you wanted to return the function and not the result of the call:
return { changeIt: changeIt };
or this which is more concise:
return { changeIt };
According to how you are using the translate function, I think you should export it this way:
const Translator = {
const translate = string => string;
};
if (module.exports) {
module.exports = Translator;
}
or this way:
const Translator = () => {
const translate = string => string;
return { translate };
}
if (module.exports) {
module.exports = Translator();
}
Return the function instead of calling it.
const ParseThis = () => {
const changeIt = string => string;
return { changeIt };
}
In the original post, changeIt() is a call to changeIt with no first parameter. It returns the value undefined. To return a function instead of calling it, omit the parenthesis.
Let's analyze your code.
Let's start from this:
const changeIt = string => string;
At this point, changeIt is a function that, given a parameter, it returns that a parameter.
Without an arrow function, if we should use the old classic named function, it would be like this:
function changeIt(parameter) {
return parameter;
}
What happens if you call changeIt() with no parameter? In javascript, when you pass no parameters ot a function, it's like you are passing undefined. So the function will return undefined.
Then you have this line:
return { changeIt: changeIt() }
But as we have seen, changeIt() is equal to undefined. So your code is equivalent to:
return { changeIt: undefined }
Which is clearly not a function!
What you probably meant to do, is not returning the result of function invokation, but return the function itself. So, instead that assigning changeIt(), just assign changeIt:
return { changeIt: changeIt }
Notice that you repeated twice the word changeIt, so you can get rid of this repetition and just write:
return { changeIt }
Your function is returning an object, so instead of
ParseThis.changeIt()
You should be doing something like
const a = ParseThis();
a.changeIt('some string');
But, note that even in your example, changeIt in the returning object is not a function.
Probably you are trying this
const ParseThis = () => {
const changeIt = string => string;
return { changeIt: changeIt};
}
Note that I've used { changeIt: changeIt}, setting changeIt to a reference of the inner function changeIt. And you are using { changeIt: changeIt()} setting changeIt to the value returned of the inner function changeIt. Those are two different operations.
The problem is that you are exporting a function, and not the object containing the nop function. You need to add parenthesis to your dummy:
const Translator = () => {
const translate = string => string;
return { translate };
};
if (module.exports) {
module.exports = Translator(); // add parenthesis here
}
Alternatively you could run the function you import, but I suspect that would be different from your real Translator api.

How to fix the issue not all the code paths return value?

I have an error in the code that I am trying to resolve. I think it needs a return statement but I have that already outside of the forEach loop but it still throws the error:
not all the code path return the value
How to fix below code?
main.ts:
private ValidateRequestArgs(str) {
let ret: boolean = true;
// here on val its throwing tslint error not all code paths return value
str.split(',').forEach((val) => {
if (!ret) {
return false;
}
if (List.indexOf(val) > -1) {
ret = true;
} else {
ret = false;
}
});
return ret;
}
The complaint is that the first if(){} is missing an else{} block with a return statement. You can disable this behaviour in a tsconfig file setting:
"noImplicitReturns": false,
Of course you could also add
else {return ...}
But I would not recommend that, since forEach is not supposed to return anything as stated for example here:
What does `return` keyword mean inside `forEach` function?
or here:
https://codeburst.io/javascript-map-vs-foreach-f38111822c0f
Instead better get rid of the first if() altogether. Cheers
tsconfig.json
compilerOptions:{
"noImplicitReturns": false
}
You can resolve this error by two ways.
By editing the noImplicitReturns attribute to false in tsconfig.json
"noImplicitReturns": false
By adding a return statement for every path in your method. If you have 10 if conditions, then you have to add 10 return statements. It seems odd, but typescript recommends return for every path.
Here we can avoid the number of paths by the use of lambda expression.
private ValidateRequestArgs(str) {
return str.split(",").every(el => List.includes(el));
}
I'm not sure why tslint is complaining, but you can write the whole thing way more elegant as:
return str.split(",").every(el => List.includes(el));
or ES6:
return str.split(",").every(el => List.indexOf(el) > -1);
If there is a return in the forEach function, then it recognizes the function as having a return type for the whole function.
There is no problem to write your loop this way:
myFunction(): boolean {
for (let item of items) {
if (condition) {
return true;
}
}
return false;
}
foreach no need to return anything; you must be remove keyword 'return' from foreach and edit and the error points to this:
private ValidateRequestArgs(str) {
let ret: boolean = true;
// here on val its throwing tslint error not all code paths return value
str.split(',').forEach((val) => {
if (!ret) {
ret = false // this correct
}
if (List.indexOf(val) > -1) {
ret = true;
} else {
ret = false;
}
});
return ret;
}
You can define the returned value for you function like the following:
functionName: (variableName: string): string | void => {
if (variableName === "a") {
return "link";
}
};
The body of the function passed to forEach has an implicit signature of any -> boolean so it would seem that tslint is expecting you to treat it more statically and return boolean on all code paths.
if you are facing this using .forEach for-loop use for-of for-loop as below,
for (var val of str.split(',')) { }

understanding the return keyword

I have this:
validateForm = () => {
for (let i = 0; i < formInputs.length; i++) {
const inputName = formInputs[i];
if (!this.state.form[inputName].length) {
return false;
}
}
}
which im refactoring in to this:
validateForm2 = () => {
Object.keys(this.state.form).map(input => {
if(!this.state.form[input].length) {
return false
}
return true;
})
}
the first one works, when i fill in my form and the function returns true, if one is empty it returns false.
however i cant seem to quite understand the return keyword to get the same result.
Object.keys says it returns an array but even if I say return Object.keys... or else {return true} I don't seem to get the same result. what am I misunderstanding about return?
You could use Array#every, which uses the return value for a short circuit and for returning the check of all truthy items.
validateForm2 = () =>
Object.keys(this.state.form).every(input => this.state.form[input].length);
Array#map utilizes the return value as new item for each item of the array for a new array, which is dicarded in the given example.
In the first example you have only one (arrow) function which returns either false or undefined.
In the second example you have outer (arrow) function that never returns anything - undefined to the calling code, and the second function that you pass as a parameter to Array.map method. return statements inside the parameter function are not returning anything from the outer function.
validateForm2 = () => {
var emptyItems = Object.keys(this.state.form).filter(input => {
return !this.state.form[input].length;
});
return emptyItems.length == 0;
}
You could modify your function to do what you want it to do.
validateForm2 = () => {
return Object.keys(this.state.form).every(input => {
return this.state.form[input].length;
})
}
You are checking that every property has a length (true). If one of them doesn't, your function returns false.
I think you can avoid using .map in favor of .every() which iterates over every single element and checks whether it has a length greater than zero.
const validateForm = (form) => Object.values(form).every((field) => field.length);
let semiEmptyForm = {
firstField : "",
secondfield : "notEmpty"
};
let nonEmptyForm = {
firstField : "notEmpty",
secondfield : "notEmpty"
};
console.log(validateForm(semiEmptyForm))
console.log(validateForm(nonEmptyForm))

JS Break out of function

I've got a method that looks like this:
return AddedSoftware (software) {
this.softwares.map(function(soft) {
if(soft.id == software) {
return software.name;
}
})
}
So how could I break and return when soft.id == software now it loops through the entire softwares before it returns!
You would use find() instead
return function AddedSoftware (software) {
let res = this.softwares.find(soft => soft.id == software);
// return the software's name if there's a match, or undefined
return res ? res.name : res;
}
This will give you the first object matching your condition. You can then get software.name from that object.
Excerpt from the docs:
The find() method returns a value of the first element in the array that satisfies the provided testing function. Otherwise undefined is returned.

Categories

Resources