Angular 11 can't access object property dynamically - javascript

I have to access to a subset of my object properties and store the label and the value in another array. Basically I have this object:
myObject: CustomObject {
prop1: value1,
prop2: value2
prop3: value3
}
and as output I need an array with objects of type: {label: string, value: number}.
I need to fill this array with prop1 and prop2 and their values, so that I have something like this:
myArray = [{label: prop1, value: value1}, {label: prop2, value: value2}]
What I've tried is this:
labels = ['prop1', 'prop2'];
labels.forEach((l: any) => {
this.myArray.push({ label: l, value: this.myObject[l] })
})
or also this.myObject.l
But I get this error:
Element implicitly has an 'any' type because expression of type 'any'
can't be used to index type 'MyObject'
I've changed the type of "l" to string but I got:
No index signature with a parameter of type 'string' was found on type
What's the correct way to do this?
myObject

Instead of any, you can use keyof to tell typescript that labels is an array of strings where strings are the keys of your interface:
Playground Link
interface CustomObject {
prop1: any;
prop2: any;
prop3: any;
}
const myObject: CustomObject = {
prop1: 1,
prop2: 2,
prop3: 3,
}
const labels: (keyof CustomObject)[] = ['prop1', 'prop2'];
const myArray = labels.map(label => ({ label, value: myObject[label] }))
console.log(myArray)

You can use Object.entries function to iterate over key/value pairs:
const myObject = { prop1: 'value1', prop2: 'value2', prop3: 'value3' }
let myArray = [];
Object.entries(myObject).map((item)=>{ myArray.push({label:item[0], value:item[1]})})
console.log(myArray)

Related

Create an array based on two objects

I have two objects, that contains same number of properties:
object1: {
prop1: 'data12',
prop2: 'data13',
prop3: 'data58',
prop4: 'xyz',
// more props here...
}
object2: {
prop1: 123,
prop2: 'email#gmail.com',
prop3: 'text',
prop4: 'bla',
// more props here...
}
I want to build an array {name: '', value: ''} based on this objects:
[
{ data12: 123 },
{ data13: 'email#gmail.com' },
{ data58: text },
{ xyz: 'bla' },
]
How can you do that? The number of properties could be different.
Just using Object.keys() can do it
let object1 = {
prop1: 'data12',
prop2: 'data13',
prop3: 'data58',
prop4: 'xyz',
}
let object2 = {
prop1: '123',
prop2: 'email#gmail.com',
prop3: 'text',
prop4: 'bla',
}
let result =[]
let obj = {}
Object.keys(object1).forEach(k =>{
obj[object1[k]] = object2[k]
})
result.push(obj)
// combined with reduce can also do it
/*
let obj =Object.keys(object1).reduce((a,c) => {
a[object1[c]] = object2[c]
return a
},{})
*/
result.push(obj)
console.log(result)

Crating a type of array of multiple objects

I want to create a type for an array of objects. The array of objects can look like this:
const troll = [
{
a: 'something',
b: 'something else'
},
{
a: 'something',
b: 'something else'
}
];
the type i am trying to use is:
export type trollType = [{ [key: string]: string }];
Then i want to use the type like this:
const troll: trollType = [
{
a: 'something',
b: 'something else'
},
{
a: 'something',
b: 'something else'
}
];
but i get this error:
Type '[{ a: string; b: string; }, { a: string; b: string; }]' is not assignable to type 'trollType'.
Source has 2 element(s) but target allows only 1
I can do something like this:
export type trollType = [{ [key: string]: string }, { [key: string]: string }];
but lets say my array of object will have 100 objects in the array.
When setting a type for an array it should in this format any[].
So in your case
export type trollType = { [key: string]: string }[];
You can try to use the Record type for storing the object attribute definitions and create an array out of it, like in the following:
type TrollType = Record<string, string>[];
const troll: TrollType = [
{
a: 'something',
b: 'something else'
},
{
a: 'something',
b: 'something else'
}
];

Flow object with unknown number of fields

How do I define the type of an object that I know has two fields for sure: id and name, and an unknown other number of fields which names follow the pattern string_string.
So, for example, an object I would have is:
{id: '1', name: 'john', 'fa2_oh': 'value'}
I know how to define the type if the object just had id and name:
{ id: string, name: string }
But how do I define the other potential keys?
As Aleksey said, you can add an indexer property, but it's not possible to specify a pattern of strings.
type BaseT = { a: string, b: number, [string]: boolean }
const foo: BaseT = { a: 'a', b: 1, hello: false }
If the pattern is somewhat bounded, you could spell out that type:
type KeysT = 'fa_oh1' | 'fa_oh2' | 'bb_aa1' | 'bb_aa2'
type BaseT = { a: string, b: number, [KeysT]: boolean }
const foo: BaseT = { a: 'a', b: 1, hello: false }

Equivalent of TypeScript Record in Flow?

TypeScript provides the utility type Record and I am looking for its equivalent in Flow.
I tried: { [key: KeyType]: Value } but that definition has a different semantic.
The equivalent is almost identical to TypeScript:
// #flow
type Record<T, V> = {
[T]: V
}
Pulling the example from the TypeScript docs:
type ThreeStringProps = Record<'prop1' | 'prop2' | 'prop3', string>
const test: ThreeStringProps = {
prop1: 'test',
prop2: 'test',
prop3: 'test',
}
// Fails because prop3 is not a string
const failingTest: ThreeStringProps = {
prop1: 'test',
prop2: 'test',
prop3: 123,
}
// Fails because `prop4` isn't a valid property
const failingTest2: ThreeStringProps = {
prop1: 'test',
prop2: 'test',
prop3: 'test',
prop4: 'test',
}
You can see this in action at Try Flow.

Renaming or setting object names dynamically in JavaScript

I'm fairly new to JavaScript I setup below to use keys and values for different items I need to work. All the values will be the same using a variable to distinguish each item (which will just be it, but I would like to identify each item (itemObject) which I'm also using for the variable name.
Abbreviated example::
function objFunction (itemName) {
itemObject = {
object1Data: [{
data1: {
prop1: 'value',
prop2: 'value'
},
data2: {
prop1: itemName + 'some string'
prop2: itemNamevariable
}
}],
object2: {
data: {
prop1: itemName,
prop2: itemName + 'some string'
}
}
}
}
Or am I better off using a constructor or another method?
function ObjFunction (itemName) {
this.itemObject = {
bject1Data: [{
data1: {
prop1: 'value',
prop2: 'value'
},
data2: {
prop1: itemName + 'some string',
prop2: itemName
}
}],
object2: {
data: {
prop1: itemName,
prop2: itemName + 'some string'
}
}
}
}
var item1 = new ObjFunction('item1Name');
I prefer the first answer, just change the second line from:
itemObject = {
to
return {
and then you can say:
var item1 = objFunction('item1Name');
In other words:
function objFunction (itemName) {
return {'name' : itemName};
}
var y = objFunction("theName");
console.log(y.name);

Categories

Resources