1

I've been googling for hours, but can't wrap my head around this issue..

I have an interface:

interface Alert {
  uuid: string,
  city: string,
  address: number
}

and I would like to itterate over a object, which is for sure compliant with this interface:

 const alerts: Alert[] = response.from.api.alerts

now when I try to do something like this I get an error in ts compiler:

for (const alert of alerts) {
 for(const field in alert) {
   // this shows an error: Element implicitly has an 'any' type... ts(7053)
   console.log(alert[field])
 }
}

what's the correct way of accesing value of alert object?

should I use a type guard or something similar?

how can I declare to typescript that field is a keyof of alert?

should I disable the noImplicitAny flag -> is this considered "best practice"?

I know this question has been asked many times, but none of the answers helped me..

Thx for any help!

7
  • Interface are not known at compile time, there could be anything in it. if you look at this example you can put anything in it. Maybe this answer could help? Commented Sep 30, 2020 at 13:49
  • Please also note that alert is a blockscoped function. Commented Sep 30, 2020 at 13:56
  • 1
    I've reviewed this answers, but non of them are relevant to the question in hand. The first one is not using an interface and the second answer is about trying to get object keys from interface, which is nice, but not my question. I'm curious how to "dynamically" access a property in typescript object. accessing alert[field] is the trick I want to learn in a typescript world. There has to be a way how to do this.. Commented Sep 30, 2020 at 13:57
  • @MoxxiManagarm could you please elaborate? Commented Sep 30, 2020 at 13:58
  • 1
    @Stutje Also, my error is not in compile time. I could pass through it with //@ts-ignore, but that's not the goal. I want to do this in some sort of "best practice" manner Commented Sep 30, 2020 at 14:00

3 Answers 3

2

So, I found a way how to deal with this error (ts.7053).

First of all, thank you all for you help, but i belive my question has been misleading. Correct question should have been -> how to access typed object with bracket notation in for loop.

I've created a new interface called Indexable, which looks like this:

export interface Indexable {
  [key: string]: any;
}

my "Alert" interface is now extending this interface:

interface Alert extends Indexable {
  uuid: string,
  city: string,
  address: number
}

now I can do a for loop on an object which is typed as "Alert" without errors:

...
 for(const field in alert) {
   console.log(alert[field]
 }
...
Sign up to request clarification or add additional context in comments.

Comments

0

You can try something like this

    alerts.forEach( (field: Alert) => {
      console.log(field.uuid);
    });

1 Comment

Hi, I don't have issue accessing the direct field, i.e alert.uuid. Maybe the question I'm asking is not exact. I want to iterate in for in loop and to dynamically access a property of a object which is typed.
0

In my opinion, if you have the interface and you are sure that the object is compliant with your interface, you shouldn't iterate over each key of the object. Underwood, typescript will believe you and assume that alerts is an array of Alerts.

So basically you could do something like this:

const alertsWithoutType: any = [
    { uuid: "uuid1", city: "city1", address: 1},
    { uuid: "uuid2", city: "city2", address: 2}
];

const alerts = alertsWithoutType as Array<Alert>;

alerts.forEach(alert => console.log(alert));

But, if you want to iterate over each key of your object, you should tell typescript that you don't know the object type:

const alerts: any = [
    { uuid: "uuid1", city: "city1", address: 1},
    { uuid: "uuid2", city: "city2", address: 2}
];

for (const alert of alerts) {
    Object.getOwnPropertyNames(alert)
        .forEach(key => 
            console.log(`key: ${key}, value: ${alert[key]}`)
        );
}

3 Comments

The thing which bugs me the most in your solution is the use of "any" keyword. Why should I use "any", if I know the type of the response? I'm not proficient in typescript, but imho this is an antipattern in typescript, which I try to use only as a last resort.
@JaniskoPsisko You should avoid using any. If you know the type, you should type your variables. Saying that, for your case, if you know the interface, why you will want to iterate over each property type of the object? You can access explicit each property using the proper type name. That is the reason which typescript is retriving you an error.
There could be numerous reasons. The example I've provided in this question is trivial, but in the real world scenario I'm dealing with, I would like to coerce the item into a proper shape I need. i.e all strings in object should be uppercased. It's a legit thing to do something like if(typeof alert[field] === 'string') let capitalizedVal = alert[field]. toUpperCase() ...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.