For a configuration system, I'd like a type that can only be used as object keys not as values, so I created a class with a toString() method like so:
const myKeys: {[key: string]: MyKey} = {};
class MyKey {
name: string;
constructor(name: string) {
this.name = name;
myKeys[name] = this;
}
toString(): string {
return this.name;
}
}
type MyMap = {[key: MyKey]: string};
const m1: MyMap = {};
const k = new MyKey('foo');
m1[k] = 'foo';
const m2: MyMap = {[k]: 'foo'};
While Flow is happy with regular object assignment, it does not work when used as a computed property:
21: const m2: MyMap = {[k]: 'foo'};
^ object literal. Computed property cannot be assigned with
21: const m2: MyMap = {[k]: 'foo'};
^ MyKey
Try (objectName:any)[variableName].
I'm using flow v0.51.1, this works well.
const myKeys: {[key: string]: MyKey} = {};
class MyKey {
name: string;
constructor(name: string) {
this.name = name;
(myKeys:any)[name] = this;
}
toString(): string {
return this.name;
}
}
type MyMap = {[key: MyKey]: string};
const m1: MyMap = {};
const k = new MyKey('foo');
(m1:any)[k] = 'foo';
const m2: MyMap = {[(k:any)]: 'foo'};
console.log(myKeys);
//=> { foo: MyKey { name: 'foo' } }
I'm looking to leverage Flow's type checking rather than require library consumers to switch it off each time they use a computed property (a frequent occurrence with this library.)
I'd hoped I might be able to work around this using opaque types, but sadly it looks not, even if I declare the opaque type with a string supertype. (I'm using declare opaque type here to simulate usage from another file.)
/* @flow */
const myKeys: {[key: string]: MyKey} = {};
class MyKey {
name: string;
constructor(name: string) {
this.name = name;
myKeys[name] = this;
}
toString(): string {
return this.name;
}
}
declare opaque type MyKeyOpaque: string;
type MyMap = {[key: MyKeyOpaque]: string};
function myKeyOpaque(name: string): MyKeyOpaque {
return (new MyKey(name): any);
}
const m1: MyMap = {};
const k = myKeyOpaque('foo');
m1[k] = 'foo';
const m2: MyMap = { [k]: 'foo' };
Errors (v0.66.0):
27: const m2: MyMap = { [k]: 'foo' };
^ Cannot assign computed property using `MyKeyOpaque` [1].
References:
19: function myKeyOpaque(name: string): MyKeyOpaque {
^ [1]
This also would be extremely helpful when using redux
const action = { type: 'foo', toString() { return this.type; } }
const reducerHandlers = {
[action]: () => {} // 馃憥 Cannot assign computed property using object literal
}
Most helpful comment
I'm looking to leverage Flow's type checking rather than require library consumers to switch it off each time they use a computed property (a frequent occurrence with this library.)
I'd hoped I might be able to work around this using opaque types, but sadly it looks not, even if I declare the opaque type with a string supertype. (I'm using
declare opaque typehere to simulate usage from another file.)Errors (v0.66.0):