Add extend function to easily extend an inherited model.
All checks were successful
/ test (push) Successful in 40s

This commit is contained in:
Madeorsk 2025-06-22 23:25:14 +02:00
parent 75b7b35dd6
commit ecd8852afa
Signed by: Madeorsk
GPG key ID: 677E51CA765BB79F
3 changed files with 58 additions and 1 deletions

View file

@ -1,5 +1,5 @@
import {Definition, UnknownDefinition} from "./property-definition";
import {ConstructorOf} from "../utils";
import {ConstructorOf, Modify} from "../utils";
/**
* A model shape.
@ -524,6 +524,32 @@ export function defineModel<T extends object, Shape extends ModelShape<T>, Ident
return new ModelManager<T, Shape, Identifier>(definition);
}
/**
* Define a new model, extending an existing one.
* @param extendedModel The extended model manager instance.
* @param definition The extension of the model definition object.
*/
export function extend<
ExtT extends object, ExtShape extends ModelShape<ExtT>, ExtIdentifier extends IdentifierDefinition<ExtT, ExtShape>,
T extends ExtT, Shape extends ModelShape<T>, Identifier extends IdentifierDefinition<T, Shape>,
ResIdentifier extends IdentifierDefinition<T, ResShape>, ResShape extends ModelShape<T> = Modify<ExtShape, Shape>
>(
extendedModel: ModelManager<ExtT, ExtShape, ExtIdentifier>,
definition: ModelDefinition<T, Shape, Identifier>,
)
{
const { properties: extendedProperties, ...overridableDefinition } = extendedModel.definition;
const { properties: propertiesExtension, ...definitionExtension } = definition;
return new ModelManager({
...overridableDefinition,
...definitionExtension,
properties: {
...extendedProperties,
...propertiesExtension,
},
}) as unknown as ModelManager<T, ResShape, ResIdentifier>;
}
/**
* A generic model manager for a provided model type, to use in circular dependencies.
*/

View file

@ -2,3 +2,8 @@
* Type definition of a class constructor.
*/
export type ConstructorOf<T extends object> = { new(): T; };
/**
* Type definition of an original object overridden by another.
*/
export type Modify<Original, Override> = Omit<Original, keyof Override> & Override;

View file

@ -106,6 +106,32 @@ function getTestArticle(): Article
}
describe("model", () => {
it("defines a new model, extending an existing one", () => {
class ExtendedAccount extends Account
{
static extendedModel = s.extend(Account.model, {
Class: ExtendedAccount,
properties: {
extendedProperty: s.property.string(),
},
});
extendedProperty: string;
}
expect(ExtendedAccount.extendedModel.definition).toEqual({
Class: ExtendedAccount,
identifier: "id",
properties: {
id: s.property.numeric(),
createdAt: s.property.date(),
name: s.property.string(),
email: s.property.string(),
active: s.property.boolean(),
extendedProperty: s.property.string(),
},
});
});
it("initializes a new model", () => {
const article = getTestArticle();
const newModel = Article.model.model(article);