We're currently adopting flow, and I'm running into an interesting problem. In one of our code-bases, we use a pattern roughly as follows.
We have 'models', which represent a 'Value object' or 'Data transfer object'. So our 'models' hold a single record. This is one of the simplest possible models:
class UserModel extends BaseModel {
}
The BaseModel defines a constructor, which roughly looks like this:
class BaseModel {
constructor(properties: Object) {
for (let key in properties) {
this[key] = properties[key];
}
}
}
This allows you to do stuff like this:
const user = new UserModel({
firstName: 'Evert',
lastName: 'Pot'
});
I'm looking for an elegant way to add type-safety to this. One of the issues I'm facing is that I'd like both typesafety in places where an instance of UserModel is passed around, as well as during the construction of UserModel. Ideally I'd like UserModel to not be allowed to be instantiated in incomplete/invalid forms.
My first pass on this (which meets this goal) is this:
/* @flow */
interface UserInterface {
firstName: string;
lastName: string;
}
class UserModel extends BaseModel implements UserInterface {
firstName: string;
lastName: string;
constructor(props: UserInterface) {
this.firstName = props.firstName;
this.lastName = props.lastName;
}
}
const user = new User({
firstName: 'Evert',
lastName: 'Pot'
});
I'm re-using UserInterface both as a type for the constructor as well as the class itself.
This works, but has the drawback that I'm repeating every property name 4 times. When defining the interface, when defining the class and when setting the property in the constructor.
Being fairly new to flow, I wonder if there's a way to reduce this. Can I remove the duplication of property names?