Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flow: computed property. Indexable signature not found in... when type is class

How to fix an error in this case (keeping using class as type):

/* @flow */

class Person {
  name: string;
  age: number;
}

const person: Person = new Person();
person.name = 'Bob';
person.age = 25;

['name', 'age'].forEach(key => {
  if(person[key]) {
    console.log(person[key]);
  }
});

The error points to person[key] and says:

Cannot get person[key] because an indexer property is missing in Person

In similar situation (may be different flow version) it says:

computed property. Indexable signature not found in Person

like image 587
Vladislav Kosovskikh Avatar asked Feb 02 '26 20:02

Vladislav Kosovskikh


1 Answers

I think the bigger issue is that Array.prototype.forEach has the type

forEach(callbackfn: (value: T, index: number, array: $ReadOnlyArray<T>) => any, thisArg?: any): void;

https://github.com/facebook/flow/blob/3baafb0f2191353cd896d6fe087aea535bc8606e/lib/core.js#L211.

You can see that the value parameter has type T, which is determined by the type of the elements in the array. In your case, Flow is (most likely) assuming the type of the array ['name', 'age'] to be string[]. Thus, the type T is set to string.

Now, when you try to access person[key], Flow will complain that you are missing an indexer property. This is accurate since you are trying to use a generic string access on the Person instance. This problem persists even after removing the conditional, which hints that Flow is unable to refine the string type to be one of 'name' and 'age'.

It would be nice if Flow could refine something like this

/* @flow */

class Person {
  name: string;
  age: number;
}

const person: Person = new Person();
person.name = 'Bob';
person.age = 25;

['name', 'age'].forEach(key => {
  if (key === 'name') {
    console.log(person[key]);
  }
});

not necessarily because it's useful but because it is so explicit and should be a safe access at that point.

I would try to avoid using a loop through a list of properties to get/set properties on an object since Flow doesn't deal with the nuances of arrays that act like tuples yet. Plus, it's more future-proof to loop through the object itself (e.g., Object.keys) in case the object's properties ever get changed.

like image 162
user11307804 Avatar answered Feb 05 '26 10:02

user11307804