So, I have a prop that will sometimes be null. I want to either get the value or return null.
I am currently doing this:
getOr(
null,
`shift.id`,
ownProps
);
I am getting the shifts.id from the props, however if there's no shift.id I'll get an error back. How can I either return shift.id or null?
The way _.getOr works is that it provides a default value (the first argument) in the case that the value referenced by the path (the second argument) cannot be found in the object (the third argument). It's actually the same as _.get but the argument order is flipped.
An example case is here:
let myObjects = [{
shift: {
id: 1,
example: "text1"
}
},
{
shift: {
id: 2,
example: "text3"
}
},
{
shift: {
example: "text2"
}
}
]
myObjects.forEach((object) => {
let result = _.getOr(null, "shift.id", object)
console.log(result);
})
<script src="https://cdn.jsdelivr.net/g/lodash#4(lodash.min.js+lodash.fp.min.js)"></script>
The console output is:
1
2
null
From what you have described though it's not clear to me that is actually what you are trying to do. Remember, get/getOr will return what's referenced by the path (even if it's already null) unless it's not there (as in undefined), at which point it will return the default value.
So in this case, where there is no shift.id you are asking _.getOr to return null. It sounds like you are then getting an error from GraphQL when you try to use it with a null value. This isn't a problem with lodash in this case, but a problem with your data / how you are using GraphQL.
If this isn't the right tool for the job then I can't suggest anything else without seeing more of your code/knowing more about the problem. I would suggest taking another look at your overall problem and then perhaps asking a different question if needs be.
I have tried your snippet with the sparse information you provided and that works as designed, as far as I understand this.
See also my repl.it.
code
const _ = require('lodash/fp');
var ownProps = { shifts : { id: 'test' }};
console.log(_.getOr(
null,
`shifts.id`,
ownProps
));
ownProps = { shifts : { foo: 'test' }};
console.log(_.getOr(
null,
`shifts.id`,
ownProps
));
output
test
null
Related
I'm having trouble getting TypeScript to recognise that an optional property of an object is defined.
type OuterKeys = 'a' | 'b';
type Inner = {
value: '';
}
type Outer = Partial<Record<OuterKeys, Inner>>;
const thisGivesError = (key: OuterKeys, outer: Outer) => {
if (outer[key]) {
console.log(outer[key].value);
}
}
Even though I explicitly check if outer[key] is defined, I'm getting error when trying to access outer[key].value: Object is possibly 'undefined'.
How can I work around it? The only way I found is assigning outer[key] to a variable and having another if, like below. Is this the only way to go?
const thisWorks = (key: OuterKeys, outer: Outer) => {
const o = outer[key];
if (o) {
console.log(o.value);
}
}
The playground with the code can be found here
Edit: I don't want to use ! operator, as it feels like a workaround - why would I tell TypeScript that this value is set using non-null assertion, if I already checked for its existence with if? Same for .? - I already have the if, so this value for sure exists and is not optional.
That's #10530, currently TS doesn't narrow down on indexed access.
Because the inner object which holds the value is never specified to not be undefined.
You can fix this by simply adding a question mark.
Ex adding a question mark:
const thisGivesError = (key: OuterKeys, outer: Outer) => {
if (outer[key]) {
console.log(outer[key]?.value);
}
}
At this point, after checking for outer[key] being truthy, it's safe to go with non-null assertion:
if (outer[key]) {
console.log(outer[key]!.value);
}
Though I don't know how to make TypeScript figure it out on its own.
You can make use of object?.key operator. You can learn more about it here.
Your final code will be:
const thisWorks = (key: OuterKeys, outer: Outer) => {
if (outer[key]) {
console.log(outer[key]?.value);
}
}
Hey first time poster/user, I have been working through some coding exercises. I wrote a piece of code that passed tests but I am unsure if this is best practice
In this sample I am iterating over an array using the filter function. I am using a call back function that will return words with length greater than 5.
sample code
const words = ['unique', 'uncanny', 'pique', 'oxymoron', 'guise'];
const interestingWords = words.filter(word => {
return word ? word.length > 5 : null
})
In my head if the condition isn't met it shouldn't even try to return. What is happening when I return a null? or is this a case where I wouldn't use ternary at all.
The best I got was from MDN https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null
The value null is written with a literal: null. null is not an identifier for a property of the global object, like undefined can be. Instead, null expresses a lack of identification, indicating that a variable points to no object. In APIs, null is often retrieved in a place where an object can be expected but no object is relevant.
So should I refrain from returning a null in this context?
All .filter's callback cares about is the truthy or falsey value returned inside it. Here, it'd be better to return that comparison directly, no conditional operator needed:
const interestingWords = words.filter(word => word.length > 5);
A construction like
return word ? word.length > 5 : null
could make sense if you needed to check a sub-property, but only if the array element existed first, eg:
const objects = [
null,
{ word: 'foo' },
{ word: 'barbar' },
null
];
const interestingObjects = objects.filter(
obj => obj ? obj.word.length > 5 : null
);
console.log(interestingObjects);
If elements of the array might be null or undefined, you can use the optional chaining operator.
const interestingWords = words.filter(word => {
return word?.length > 5
})
I need some help please. I have a simple Angular app that takes some form input values. These values get passed to a simple method, where the values are assigned to the matching property values of an object. Finally this object is pushed into an array.
My problem is this; every time the values passed into the method are assigned to the my object's property values, all other objects' (already in my array) properties gets updated as well.
What am I doing wrong(I believe this is going to be one of those coding bloopers I will fondly remember...one day)?
My Code:
This is the object the values are assigned to:
UOPSim: Sim = {
simId: null,
simType: '',
imageUrl: '',
simCustomName: '',
simDescription_Line1: '',
simDescription_Line2: '',
simDescription_Line3: '',
simDescription_Line4: '',
peakGigLimit: null,
peakAmount: null,
monthlyGigLimit: null,
monthlyAmount: null,
};
This is my method:
onAddSimToCart(sim) {
if (sim.simType === 'UOP') {
this.UOPSim.simId = this.simsInCart.length + 1;
this.UOPSim.simType = sim.simType;
this.UOPSim.simCustomName = sim.simCustomName;
this.UOPSim.peakGigLimit = sim.peakGigLimit;
this.UOPSim.peakAmount = sim.peakAmount;
this.UOPSim.monthlyGigLimit = sim.monthlyGigLimit;
this.UOPSim.monthlyAmount = sim.monthlyAmount;
this.simsInCart.push(this.UOPSim);
} else {
// do stuff
}
}
Thank you in advance!
In case someone happens upon this question, this is how I resolved my issue:
As per #mbojko answer that was posted, I was simply referencing the same Object (newb move!).
I solved this by simply doping the following:
If you want shallow copy, use Object.assign({}, a)
For "deep" copy, use JSON.parse(JSON.stringify(a))
*Thanks to #Tareq for his answer to the post here: How do I correctly clone a JavaScript object?
So in my case I changed this.simsInCart.push(this.UOPSim); to:
const newSim = JSON.parse(JSON.stringify(this.UOPSim));
this.simsInCart.push(newSim);
Angular and TypeScript have nothing to do with that. It's simple JavaScript:
this.simsInCart.push(this.UOPSim);
If the components keep one UOPSim, then you don't have n objects in your array, you have n references to the same object.
You can clone it one way or another:
this.simsInCart.push({ ...this.UOPSim });
While building a Todo app, I want to filter out an object out of my array with a remove function. So far I got this.
deleteTask(task) {
let taskList = this.state.tasks;
var newTask = taskList.filter(function(_task) { return _task != task})
this.setState({
tasks: newTask
});
}
Only problem is, the function returns the whole array while using the function.
So the Task argument that should return just an object out of my array returns the whole array instead while in my newTask var.
How can I bind or make this function work?
The array which I am wanting to remove an object from is not located in the same Component, dont know if that matters. But for extra info.
First off, let's see why _task != task doesn't work as you need. Try this:
const a = { x: 10, y: 'hello' };
const b = { x: 10, y: 'hello' };
console.log(
a==b,
a===b,
Object.is(a,b)
);
Suprising, eh? Read this for more details.
Anyway, you should refactor your code to include an id property in your tasks, so that you can compare two tasks with their ids - no need to worry about weird implementations of object comparisons in JavaScript!
This should then work:
deleteTask(taskId) {
this.setState(prevState => ({
tasks: prevState.tasks.filter(task => task.id !== taskId)
}));
}
Equality operator in javascript compares the references of the object. So even if both object have same value, since they point to different instances, == will always return false. So as I see you have two options:
Refactor your code to include a id part and which that to compare two tasks.
Use some library like lodash or underscore for deep comparison
I am currently in a accelerated codeing program and I am having trouble writing out code. Or more so, deciphering a question that asks me to write out code.
for example: * Given an input Object, loop over the Object and print its values using console.log().
what I deciphered is it wants me to do a for loop but its an object so I need to use a for in loop.
here's what I've done so far:
function printObjectValues(object) {
var object = {
one: 1,
two: 2,
three: 3,
};
for (var key in object) {
console.log(object[key])
}
In checking it says I'm still wrong. "An assertion error: expected false to be true."
what am i doing wrong?
object should be outside of the function, otherwise, there's no point in using a function. The code you have provided is working correctly. It is logging the values of all elements in the object:
var object = {
one: "first",
two: "second",
three: "third",
};
function printObjectValues(object) {
for (var key in object) {
console.log(`${key} => ${object[key]}`)
}
}
printObjectValues(object)