Is it possible to pass Typescript decorator object values in at runtime?
Asked Answered
B

2

5

I have a class that is decorated with a @MinDate constraint like this:

export default class Order {
   purchaseDate: Date;
   @MinDate(this.purchaseDate)
   receiptDate: Date;
}

When attempting to validate an instance of Order that is valid the validation errors out. My question is is it even possible / valid to pass in this.purchaseDate as an argument to the @MinDate() decorator.

In other words can typescript decorators receive runtime values from an object, or do these values have to be available at compile time? So for example:

@MinDate(new Date(12/22/2017));  //This should work?
@MinDate(this.someDate) // This will never work?
Bucher answered 2/5, 2017 at 16:11 Comment(0)
R
4

No, you can't do that.
Decorators are applied to the classes and not the instances, meaning that there's no this when the decorator function is invoked.

Using a static value will work:

@MinDate(new Date(12/22/2017));

But you can't use an instance member for it.

You can do that in the constructor without a decorator:

export default class Order {
    ...
    constructor() {
        this.purchaseDate = ...
        this.receiptDate = this.purchaseDate;
    }
}
Resurrect answered 2/5, 2017 at 16:34 Comment(1)
What about method decorators?Poppo
A
4

It's possible using a custom validator:

    import {registerDecorator, ValidationOptions, ValidationArguments} from "class-validator";

export function IsGreaterThan(property: string, validationOptions?: ValidationOptions) {
   return function (object: Object, propertyName: string) {
        registerDecorator({
            name: "IsGreaterThan",
            target: object.constructor,
            propertyName: propertyName,
            constraints: [property],
            options: validationOptions,
            validator: {
                validate(value: any, args: ValidationArguments) {
                    const [relatedPropertyName] = args.constraints;
                    const relatedValue = args.object[relatedPropertyName];
                    return value > relatedValue;
                }
            }
        });
   };
}

Usage:

import { IsGreaterThan } from "./IsLongerThan";

export class Post {
    purchaseDate: string;

    @IsGreaterThan("purchaseDate", { message: "receiptDate must be greater than purchaseDate" })
    text: string;
}

More details can be found in documentation: https://github.com/typestack/class-validator#custom-validation-decorators

Auspice answered 27/3, 2020 at 15:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.