0

I'm using Object.keys to iterate over an object and I want to execute some logic when the type is an Array. I had even added a check to see whether the value is an array but still TypeScript doesn't infer the value as an array. Is there any way to solve this?

type Test {
  length: number[];
  name: string;
  [key: string]: number[] | string;
}

const test:Test = {
  length: [10, 20 ,30],
  name: 'test'
}

Object.keys(test).map(key => {
  if(Array.isArray(test[key])) {
    test[key].map(i => i)
  }
})

Playground

1 Answer 1

3

TypeScript is having a hard time keeping track of the discriminated type of Test[string] after the check.

TypeScript can do this with local variables:

if (Array.isArray(someObj)) { someObj.map(() => /*...*/ }

Or explicit properties:

if (Array.isArray(someObj.myArr)) { someObj.myArr.map(() => /*...*/ }

But when the index type is something generic like string, it doesn't quite have enough info for the compiler to figure this inference out.

This has been discussed by the TypeScript team if you want to read more about this. The issue is currently open. Maybe it will be supported in the future, as it does look like the compiler should be able to figure this one out, in theory. (Thanks for the layup @jcalz)


The simplest solution is to change your code into one of the above forms. I would suggest storing a reference to the property value in a local variable and then testing/using that. This allows TypeScript to track type narrowing on that variable.

Object.keys(test).map(key => {
  const maybeArray = test[key]
  if(Array.isArray(maybeArray)) {
    maybeArray.map(i => i)
  }
})

Playground

Sign up to request clarification or add additional context in comments.

2 Comments

Rather than post the answer I'm working on, I'll just ask you to include a link to microsoft/TypeScript#10530, the issue about the inability to use control flow analysis to narrow the type of an object's property if the index is a variable like test[key].
Thanks! Added. Your answer probably would have been better. They usually are :)

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.