'How to do conditional defining of key in an object in JS?
Suppose I want to create an object with keys as USD and non-USD. Like Below:
let obj = {
USD: {
sourceValue: 100
destinationValue: 10
},
non-USD: {
sourceValue: 10
destinationValue: 100
}
}
Except here, instead of non-USD, I should be able to pass any currency, like SGD or HKD and I should get result of non-USD currency.
so, if I wrote obj[currency].sourceValue and currency=HKD then I should get 10
I don't want to use obj[1].sourceValue as currency value is dynamic.
Also, I don't want to use if(currency!='USD') index=1 and then obj[index].sourceValue
So, my question is, what should I write at place of non-USD while defining object? I checked computation names, but I am not sure, how will I pass long currency array as key name and filter USD out of it?
Solution 1:[1]
I don't know of an option in js/ts that would have the key lookup syntax (like obj[currency]) and do the behavior that you want, while keeping the object obj "plain".
But there are options that do what you want with some modifications to the obj and/or with a different call syntax. (The only way that I can think of that would keep the obj completely untouched would require some changes to the currencies then.)
Option 1: add a get function call
const obj1 = {
get: function(currency) {
return this[currency === "USD" ? "USD" : "non-USD"]
},
USD: {
sourceValue: 100,
destinationValue: 10
},
"non-USD": {
sourceValue: 10,
destinationValue: 100
}
}
Or if you cannot change the object's source use Object.assign.
Here you can decide if you want to mutate the original object (Object.assign(target, ...)) or create a new one with Object.assign({}, target, ...)
const addGetter = (target) => Object.assign({}, target, {
get: (currency) => target[currency === "USD" ? "USD" : "non-USD"]
})
const obj1 = addGetter(obj) // <-- pass in the original obj
Usage: obj1.get(currency).sourceValue
Option 2: using a Proxy
Offers the key lookup syntax that you want, but imo, this approach is a bit error-prone, because any access (indexed, by key or property) other than "USD" will return the "non-USD" values. Also the object gets wrapped, which hides object details when logging (console.log(obj)) in some consoles.
const useProxy = (obj) => new Proxy(obj, {
get: (target, currency) => target[currency === "USD" ? "USD" : "non-USD"]
})
const obj2 = useProxy(obj) // <-- pass in the original obj
Usage: obj2[currency].sourceValue
Demo
Check the code comments and the console output
const addGetter = (target) => Object.assign({}, target, {
get: (currency) => target[currency === "USD" ? "USD" : "non-USD"]
})
const useProxy = (obj) => new Proxy(obj, {
get: (target, currency) => target[currency === "USD" ? "USD" : "non-USD"]
})
const obj = {
USD: {
sourceValue: 100,
destinationValue: 10
},
"non-USD": {
sourceValue: 10,
destinationValue: 100
}
}
// Option 1
const obj1 = addGetter(obj)
// Option 2
const obj2 = useProxy(obj)
const c = ["USD", "EUR", "HKD", "non-USD"]
console.log("obj1.get(currency).sourceValue", c.map(currency => currency + " -> " + obj1.get(currency).sourceValue))
console.log("obj2[currency].sourceValue", c.map(currency => currency + " -> " + obj2[currency].sourceValue))
// Option 2 feels a bit error-prone, as any other access will return the fallback value for "non-USD"
console.log("obj2.length", c.map(currency => obj2.length))
console.log("obj2.randomProp", c.map(currency => obj2.randomProp))
Solution 2:[2]
You ll actually need to use the if else like condition. say like this
const key = currency == "USD" ? "USD" : "non-USD";
// and then get the data like this
obj[currency].sourceValue
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Omkar Kulkarni |
