I have this object model:
export class FrcCapacity {
constructor(
public id?: number,
public frcId?: number,
public capGroupId?: number,
public capGroup?: CapGroup,
public salesProductId?: number,
public p1?: number,
public p2?: number,
public p3?: number,
public p4?: number,
public p5?: number,
public p6?: number,
public p7?: number,
public p8?: number,
public p9?: number,
public p10?: number,
public p11?: number,
public p12?: number,
public total?: number
) {}
}
And I have an array of this, f. e. frcCapacity, filled with objects of the above object model.
I want to write a function, where I want to set the px value of the processed object. For this, I have all needed data and the function body looks like this:
periodValueChange(val: string, rowIndex: number, field: string) {
for (let [key, value] of Object.entries(this.frcCapacity[rowIndex])) {
if (key === field) this.frcCapacity[rowIndex]???
}
}
I'm trying this with Object.entries, but what should I write in place of the ???. How can I access the px field based on the field string parameter?
After some thinking and searching, this solution works:
periodValueChange(val: string, rowIndex: number, field: string) {
let frcCap = this.frcCapacity[rowIndex];
let map = new Map(Object.entries(frcCap));
for (let [key, value] of map) {
if (key === field) {
map.set(field, val);
}
}
let obj = Array.from(map).reduce(
(obj, [key, value]) => Object.assign(obj, { [key]: value }),
{}
);
this.frcCapacity[rowIndex] = obj;
}
Basically, I needed something like this:
periodValueChange(val: string, rowIndex: number, field: string) {
this.frcCapacity[rowIndex].field = val;
}
Where the field parameter can be p1, p2, etc.
CodePudding user response:
Since you've used string for both the property name (field) and the value (val), I'm going to assume that you're getting those strings from somewhere that you can't get non-strings from (like form fields). So there are two challenges:
fieldcould be an invalid property name forFrcCapacityobjects, andvalmay not be a valid value for whatever propertyfieldidentifies.
To handle this in a mostly-typesafe way, you'll need a function that validates that a key is a valid FrcCapacity key, such as a type assertion function:
function assertIsValidFrcCapacityKey(key: string): asserts key is keyof FrcCapacity {
switch (key) {
case "id":
case "frcId":
case "capGroupId":
// ...and so on for all the valid property names...
break;
default:
throw new Error(`${key} is not a valid key for FrcCapacity objects`);
}
}
That tells TypeScript that if that function doesn't throw, the key passed in is a valid key for FrcCapacity objects. Obviously, it's less than ideal that you have to repeat all the property names, but there we are.
Then you have to handle the number / CapGroup thing, which you can hardcode into the function:
periodValueChange(val: string, rowIndex: number, field: string) {
assertIsValidFrcCapacityKey(field);
if (field === "capGroup") {
frcCapacity[rowIndex].capGroup = convertStringToCapGroup(val);
} else {
frcCapacity[rowIndex][field] = val;
}
}
(In that example I've used unary to convert the val string to a number, but there are other ways; I list the various options and their pros and cons here. I've also left the implementation of convertStringToCapGroup to you, since I don't know what a CapGroup is, nor how you're encoding it as a string in your form.)
