Comments (6)
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.
Thank's for submitting a fix, but i'll check on my side if there's not another way to fix the problem. By taking a quick glance, your pull requests seems a bit "hacky" to me atm.
I'll take a closer look at it at the end of the week. I'll keep you informed !
from fastest-validator-decorators.
Great thanks
from fastest-validator-decorators.
The problem
class 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 declare
instead of the !
. The difference is that ! seems to create the property with undefined and declare just tells typescript that the property will exists, so it is not overridden by the child class.
Why it is working in the tests
It seems that the !
in the tests behaves like the declare
keyword for an unknown reason. It may depends on the typescript transpiler.
The solution
There are 3 ways to solve the problem :
-
use declare
-
don't use the SchemaBase syntax
-
The code below
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.
from fastest-validator-decorators.
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 :
from fastest-validator-decorators.
Hi yes this works. If you were to remove SchemaBase in the future is it just a case of...
const data = { ...props };
const mySchema = new DataSchema();
Object.assign(mySchema, data);
I mean that is ok, but as it stands when extending SchemaBase its super clean and succint.
from fastest-validator-decorators.
I'm still not sure about removing the SchemaBase or not ... We will see in the future !
I'm closing the ticket, thank you for your contribution !
from fastest-validator-decorators.
Related Issues (14)
- Extend from SchemaBase prevents use of generics as argument HOT 1
- Docs: use of @Custom decorator HOT 2
- PR HOT 14
- Extending a schema class mixes up properties HOT 3
- Error with Nested decorator HOT 1
- Async support
- NestedArray Optionnel HOT 1
- "Nested" decorator on react enviroment (or front-end, webpack?) HOT 3
- Migration to 2 HOT 1
- Any way to support multi ? HOT 6
- Default values HOT 3
- Custom validation example HOT 3
- Instances of class decorated with "Schema" lose constructor name
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from fastest-validator-decorators.