We support indexable signatures in interfaces and "declare class" but not real class declarations.
class C {
[key: string]: number;
}
var c: C = new C();
c[""] = 0; // OK
c[0] = 0; // error
c[""] = ""; // error
Could we also add mixins
support to classes and not just class declarations? Otherwise certain patterns are very awkward as you essentially have to create class stub files just so you can mixin an interface.
@samwgoldman I might be missing something here but the "declare class" syntax does not seem to work for me. Any ideas?
Ie. https://flowtype.org/try/#0PQKgBAAgZgNg9gdzCYAoAJgUwMYwIYBOmYueAzmWAKIB2ArgLYA8AygFxgDyARgFY4AXAHxgA3qjBgA2gGtMATw5kBBAJY0A5gF0OeGvIDcEknBrKCdbALgEAFGQ4sAlBwBucVeiOSADgTg+mAQCqpgOXHyC3mCueDB0YRwAggQEePJMevJCRgC+qKjYpspgeGAAvGA0mEi0jLaiACpULI0cAIy5TkaoeAB0fgFBIWFG-bHxo719za09QA
Hi, what's the status ? Thanks!
as a temporary (and ugly) workaround we can do
class C { foo: number }
const key = 'foo';
const c = new C();
(c: Object)[key] = 42;
Just ran into this very issue minutes ago so it's a genuine use case.
In my particular situation I am using the new "implements" feature to implement an interface which has an indexable signature. Flow complains about my class which implements such interface with:
property $value
of Foo. Indexable signature not found in.
Is there a nice, succinct way to use the "ugly workaround" when we're doing all our flow stuff via comments?
+1
My workaround:
interface Indexable {
[key: string]: string
}
class MyIndexable implements Indexable {
$key: any;
$value: any;
...
}
works just like the one below should
class MyIndexable {
[key: string]: string;
}
except myIndexable['prop']
is fine but myIndexable.prop
isn't.
any progress on this?
can somebody point in out where is the code related to fix this?
Question for the Flow devs:
The $key
/ $value
syntax on classes isn't documented but seems to work great (with and without the interface
syntax @mhagmajer mentioned above). Is there any danger of this being removed somewhere down the line?
I'm finding it very useful but I'm not sure whether to rely on it? I suppose it'll be replaced by [indexer: string]
syntax at some point?
class MyClass {
$key: number;
$value: boolean | number;
}
const myObj = new MyClass();
// Works correctly!!
(myObj[1]: string | number);
Yes, there is imminent danger of this being removed.
It is unlikely that we are going to support this in the near term. We are working toward a model where the layout of instances are more precise, and this looseness would be problematic.
For example, the indexer might shadow properties on a superclass.
The better choice here is to create a data: { [K]: V }
field in your class instead of making the instance itself a dictionary.
I thought I'd share a case where this kind of behavior is ideal:
In this example, we have a simple class making use of array methods to dramatically shorten LOC and bug surface.
If support for
$key: string
$value: number
were dropped, the class would need to be reworked to scope the r
, g
and b
properties under something like values
, and property access would take the form of Color.values.r
vs Color.r
, which in my opinion is clumsy for such a simple use case and is behavior I would seek to avoid when writing some libraries.
I agree that using the key/value definitions is a hacky approach and would prefer something more standardized and streamlined for cases like the above.
@samwgoldman Is there still imminent danger of this being removed? It is very useful to us as $key: string
and $value: mixed
, forcing the developer to check the type of what he uses. This removes outright type errors that force a $FlowIgnore
, that may mask real errors. In total, adding it to some of our base datastructures has made our code more sound.
Is there any update on this?
We have no plans to support this right now, as the indexable signature is overly loose and particularly dangerous when combined with subclassing / prototype chains. Flow has no way of knowing if a [string]: T
indexer will shadow a method defined in the class itself or any of the methods / fields defined in the superclass.
The $key/$value hack will be removed, although the timeline is unclear. This was an internal implementation detail (a hack) that was never meant to be user visible.
The better choice here continues to be a data: {[K]: V}
indexer type.
@samwgoldman is it at least possible to fix this on declare class
? https://github.com/facebook/flow/issues/4014
Most helpful comment
Hi, what's the status ? Thanks!