1

I have an object:

interface MYInterface {
  aaa: number;
  bbb: number;
  ccc?: number | undefined;
}

const myObject: MYInterface = {
  aaa: 0,
  bbb: 0,
  ccc: 132,
};

I want to check if some keys in this object, satisfy a condition! I'm using Array.some(...) like below:

const res = ['aaa', 'bbb'].some((key) => myObject[key] > 0)

but for myObject[key] I'm getting a TypeScript error about:

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'INxStateCounts'.
  No index signature with a parameter of type 'string' was found on type 'INxStateCounts'.

I know that what am I trying to do is checking array of strings (keys) with objects but my array contains those keys in string.

I have tried to cast key as keyof MYInterface but no luck! I was getting so many other errors. How can I fix this?

Also my object is very big, here I use 3 properties to demonstrate the issue.

Just in case if you want to test.

halfer
  • 19,824
  • 17
  • 99
  • 186
amdev
  • 6,703
  • 6
  • 42
  • 64
  • Does this answer your question? [Typescript get object property type from name](https://stackoverflow.com/questions/58974875/typescript-get-object-property-type-from-name) – Peter B Feb 08 '23 at 11:18
  • how can i use it with `some(...)`? That is where i stuck tbh – amdev Feb 08 '23 at 11:19

4 Answers4

3

Just make more concrete typing in your code, like this:

function someOf<T>(keys: (keyof T)[], obj: T): boolean {
  return keys.some((key) => obj[key] > 0)
}

const res = someOf(['aaa', 'bbb'], myObject);
Anton Marinenko
  • 2,749
  • 1
  • 10
  • 16
  • what is the typeof T when you calling function like `someOf(['aaa', 'bbb'], myObject)`? – amdev Feb 08 '23 at 11:59
  • My understanding is `MYInterface`, and i should call it like `someOf(['aaa', 'bbb'], myObject)` – amdev Feb 08 '23 at 12:03
  • why extracting it into function does not give you error? but having it in one line does? why i still getting error with this: `(['aaa', 'bbb'] as (keyof MYInterface)[]).some(key => (myObject as MYInterface)[key] > 0)` – amdev Feb 08 '23 at 12:08
  • There is a simple reason for that, you have optional property `ccc` and it can be undefined. When it's inside the function, generic typing doesn't know about that. – Anton Marinenko Feb 08 '23 at 14:02
1

You can write something like this:

const keys : Array<keyof MYInterface> = ['aaa', 'bbb']

const res = keys.some((key) => (myObject[key] !== undefined && myObject[key]! > 0))

for some reason the bang ! operator is needed despite undefined checking.

Riadh Adrani
  • 486
  • 2
  • 5
  • 16
0

If you use object index signature you might get what you are looking for. Try:

interface MYInterface {
  [key:string]: number;
}
...

Other ways to approach this: How to dynamically assign properties to an object in TypeScript

Emilio Lucas Ceroleni
  • 1,559
  • 2
  • 9
  • 13
0

You can add as const to make it a tuple type. Then, the type of key argument will become 'aaa'|'bbb' instaed of string/any.

const res = (['aaa', 'bbb'] as const).some((key) => myObject[key] > 0)