Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I pass additional arguments to a property decorator in TypeScript?

I have this simple class with a property that has a property decorator applied to it:

class MyClass {
    @collectionMember
    public myProperty: number[];

    // ...
}

And the decorator function:

function collectionMember(target: Object, propertyKey: string | symbol): void {
    // ...
}

How can I pass additional arguments to the decorator function? I tried doing the following with no avail:

class MyClass {
    @collectionMember("MyProp")
    public myProperty: number[];

    // ...
}

Obviously, this yields the error

Supplied parameters do not match any signature of call target.

like image 243
John Weisz Avatar asked Jan 22 '16 16:01

John Weisz


People also ask

How do you use a decorator in TypeScript?

Using Decorator Syntax In TypeScript, you can create decorators using the special syntax @expression , where expression is a function that will be called automatically during runtime with details about the target of the decorator. The target of a decorator depends on where you add them.

Are decorators still experimental in TypeScript?

NOTE: Decorators are an experimental feature and are still in stage 2 in JavaScript, also, experimental in TypeScript, so it might change in the future.

How many decorators can be applied to a declaration?

It's possible to use as many decorators on the same piece of code as you desire, and they'll be applied in the order that you declare them. This defines a class and applies three decorators — two to the class itself, and one to a property of the class: @log could log all access to the class.

What are class decorators in TypeScript?

The TypeScript website describes it as: “A Decorator is a special kind of declaration that can be attached to a class declaration, method, accessor, property, or parameter.” I would describe it as “a special declaration to add extra features on an existing class declaration, method, accessor, property, or parameter.”


1 Answers

It can be done by using a decorator factory.

The factory, is just a function that receives any parameters you want and returns a function with a decorator signature:

// any parameters, even optional ones!
function collectionMember(a: string, b?: number) {
    // the original decorator
    function actualDecorator(target: Object, property: string | symbol): void {
        // do something with the stuff
        console.log(a);
        console.log(target);
    }

    // return the decorator
    return actualDecorator;
}

And then you can use it as you described.

class MyClass {
    @collectionMember('MyProp') // 2nd parameter is not needed for this array
    public myProperty: number[] = [1, 2, 3, 4, 5];

    // ...
}
like image 139
toskv Avatar answered Sep 18 '22 19:09

toskv