0

I have an array with a combination of strings and objects. Then I tried to display the properties of the array based on the key in a loop. Is it possible to do this in typescript?

This is the sample code:

const arr = [
  { name: 'John' },
  'Amber',
  { name: 'Cathrine' },
  'Louis',
  { name: 'Mike' }
]

arr.forEach((item, key) => {
  if (typeof item !== 'string') {
    console.log(item.name) // Works
    console.log(arr[key].name) // Doesn't work, losing type
  }
}

Please check this link to run the code: https://www.typescriptlang.org/play?#code/MYewdgzgLgBAhgJwTAvDA2gKBjA3jMOAWwFMAuGAcgCkQALMSmAXwBpsqBBIgIxIUrsc+QqQqUAwnCh0EASzAkmbDpQAyIAK5yIgjiOLkqAWTkBrJS0wBdTJkQIAdADMQCAKJxgdABQ+5UCRErDAWAJ4AlKgAfHgccs4wPlBhAA4kIIkBQTAAhCholNDyYADmlFG4HDigkCAANiSO9SCl-oFEjqIkUQD0vTAA6m5mENUwtRANTS1tDujh1l2GfQMAIiAkEIywAO4jIS0gEAqlMCnpHMyYzEA

I really appreciate your help, Thank you!

8
  • It's not at all clear what the problem is. If you fix the snippet so that it's runnable and doesn't have the syntax error, both console.logs print the same thing. Also unclear what "losing type" means there. Commented Dec 3, 2020 at 16:02
  • Hi thank you for your reply, please check this link to run the code. typescriptlang.org/play?#code/… Commented Dec 3, 2020 at 16:05
  • As you can see I am losing type when trying to access the 'name' property from the array. I need it to access directly from the array, not from the looping. Commented Dec 3, 2020 at 16:09
  • Not sure why you'd ever need to do that but in that case either const myItem = arr[key]; if(typeof myItem !== 'string') { console.log(myItem.name); } or console.log((arr[key] as {name: string}).name) Commented Dec 3, 2020 at 16:12
  • 1
    why not simply use item.name? Commented Dec 3, 2020 at 18:52

1 Answer 1

1

This is how type guards work in TypeScript. They only filter the type of variable that is checked. In your case you are checking for item (in typeof item !== 'string') and therefore only item is assumed to be not a string.

Fix

If you want to access arr[key].name then store that in a variable, type check that variable with a type guard, and then you are good to go.

Full fixed example:

const arr = [
  { name: 'John' },
  'Amber',
  { name: 'Cathrine' },
  'Louis',
  { name: 'Mike' }
]

arr.forEach((item, key) => {
  const member = arr[key];
  if (typeof  member !== 'string') {
    console.log(member.name) // Okay
  }
});
Sign up to request clarification or add additional context in comments.

3 Comments

let menuItem = menu[key] as typeof item I'm currently using type assertions as suggested by @Guy Incognito in the comments above, but I think your code is a better solution. What do you think?
Actually, I've tried your code before but with a different syntax instead of storing the arr[key] to a new variable. I directly checked arr[key] in the if statement, but it didn't work. Is there an explanation of why it doesn't work?
if (typeof arr[key] !== 'string') { console.log(arr[key].name) } My previous code was like this. Btw, I really thank you for your answer, it helps a lot.

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.