I'm trying to construct several typed models which can be handled in a similar manner prior to sending to storage. However, I can't figure out a way to determine each models' model::serialize()
return type.
Base interfaces/model class:
interface ModelSerialized {}
interface ModelInterface {
serialize(): ModelSerialized;
}
abstract class Model implements ModelInterface {
serialize(): ModelSerialized {
return {};
}
}
An example User model:
interface UserSerialized {
firstName: string;
lastName: string;
}
class User extends Model {
public firstName: string;
public lastName: string;
public constructor(props: UserSerialized) {
super();
this.firstName = props.firstName;
this.lastName = props.lastName;
}
get name(): string {
return `${this.firstName} ${this.lastName}`;
}
serialize(): UserSerialized {
return {
...super.serialize(),
...{
firstName: this.firstName,
lastName: this.lastName,
},
};
}
}
This would live in a separate storage class and handle all models relatively uniformly
interface AuditAttributes {
updatedAt: string;
}
function serializedAuditModel(
model: ModelInterface
): ModelSerialized & AuditAttributes {
return {
...model.serialize(),
...{
updatedAt: new Date().toISOString(),
},
};
}
A test (w/ expected output in comments)
const userAudit = serializedAuditModel(
new User({ firstName: "Foo", lastName: "Bar" })
);
console.log("User", {
firstName: userAudit.firstName, // Property 'firstName' does not exist on type 'ModelSerialized & AuditAttributes'.
lastName: userAudit.lastName, // Property 'lastName' does not exist on type 'ModelSerialized & AuditAttributes'.
updatedAt: userAudit.updatedAt,
})
I'd be inclined to make serializedAuditModel()
generic in the type S
corresponding to the output of the model's serialize()
method. Like this:
function serializedAuditModel<S>(
model: { serialize(): S }
): S & AuditAttributes {
return {
...model.serialize(),
...{
updatedAt: new Date().toISOString(),
},
};
}
Then when you call it on a user
, you get a more specific type:
const userAudit = serializedAuditModel(user);
// const userAudit: UserSerialized & AuditAttributes
which should be known to have the properties you care about:
console.log("User", {
firstName: userAudit.firstName, // okay
lastName: userAudit.lastName, // okay
updatedAt: userAudit.updatedAt, // okay
})
Hope that helps; good luck!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.