-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Extending SchemaBase is not producing object with values #27
Comments
Hello, It's strange indeed, i use the SchemaBase syntax in my projects but i don't have this kind of behavior on my side. I'll take a closer look at it at the end of the week. I'll keep you informed ! |
Great thanks |
The problemclass SchemaBase {
constructor(props: any) {
Object.assign(this, props);
}
}
class Test extends SchemaBase {
prop!: string; // undefined
}
const email = new Test({prop: "[email protected]"});
console.log(email); // <-- Test { prop: undefined } The reason it is not working is that the parent constructor is called before the child constructor. The defined properties in the child override the parent properties with undefined. The behavior is well described in this StackOverflow post : https://stackoverflow.com/questions/56790983/object-assigned-in-base-class-does-not-change-the-child-class Why it was working in my projects :class Test extends SchemaBase {
declare prop: string; // does not exists
} I use Why it is working in the testsIt seems that the The solutionThere are 3 ways to solve the problem :
import { Email, Schema, SchemaBase } from "fastest-validator-decorators";
function PatchConstructor () {
return function _DecoratorName<T extends {new (...args: any[]): {}}>(constr: T) {
if (constr.prototype instanceof SchemaBase) {
return class extends constr {
constructor (...args: any[]) {
super(...args)
Object.assign(this, args[0]);
}
}
}
return constr;
}
}
@PatchConstructor()
@Schema()
class Test extends SchemaBase {
@Email()
prop: string;
}
const email = new Test({prop: "[email protected]"})
console.log("email class before validation", email);
const result = email.validate();
console.log("validation result", result);
console.log("email class after validation", email); I'll probably apply a similar patch to the Schema constructor. export function Schema (schemaOptions?: StrictMode | SchemaOptions, messages = {}): any {
return function _Schema<T extends {new (): any}>(target: any): any {
/**
* Support old way of assign schema options
*/
schemaOptions = typeof schemaOptions === "boolean" || typeof schemaOptions === "string" ? {
strict : schemaOptions
}: schemaOptions;
if (target.prototype instanceof SchemaBase) {
target = class extends target {
constructor (...args: any[]) {
super(...args);
Object.assign(this, args[0]);
}
};
}
updateSchema(target.prototype, "$$strict", schemaOptions?.strict ?? false);
if (schemaOptions?.async !== undefined) {
updateSchema(target.prototype, "$$async", schemaOptions.async);
}
const s = getSchema(target);
const v = new FastestValidator({ useNewCustomCheckerFunction: true, messages });
/**
* Make a copy of the schema, in order to keep the original from being overriden or deleted by fastest-validator
* $$async key is removed from schema object at compile()
* https://github.com/icebob/fastest-validator/blob/a746f9311d3ebeda986e4896d39619bfc925ce65/lib/validator.js#L176
*/
Reflect.defineMetadata(COMPILE_KEY, v.compile({...s}), target);
return target;
};
} With this patch the tests pass except one : "should preserve the constructor name on instancies". i'm still thinking how to solve that problem. I will maybe remove the SchemaBase syntax in version 2.x. And let the user deal with the way he assigns the properties on the class. |
I created a new release named 1.3.1-beta.0. You can check if it fixes the problem on your side. Your Pull Request #28 was working fine in the tests but the properties were lost until the Object was validated. So it'll probably break some things in production. I added a test for this case :
|
Hi yes this works. If you were to remove SchemaBase in the future is it just a case of...
I mean that is ok, but as it stands when extending SchemaBase its super clean and succint. |
I'm still not sure about removing the SchemaBase or not ... We will see in the future ! |
fastest-validator: 1.12.0
When I follow the example to extend SchemaBase to use the constructor get a new object, the property values are always undefined, (except any properties that are on the original object but not in the schema - they remain untouched).
i.e.
I put some console.logs into the src at https://github.com/AmauryD/fastest-validator-decorators/blob/master/src/index.ts#L148 and can confirm at this point the object has all the values. But somewhere they are getting lost.
The text was updated successfully, but these errors were encountered: