karaxuna karaxuna - 1 month ago 17
React JSX Question

Extend prototype using decorator

I want to add method

setStatePromisified
to react component's prototype, I'm trying to achieve this using decorators:

interface IPromisifiedComponent {
setStatePromise: (state) => Promise<void>
}

interface IPromisifiedComponentConstructor {
new (...args): IPromisifiedComponent;
readonly prototype: IPromisifiedComponent;
}

function promisifiedDecorator() {
return function (Component: IPromisifiedComponentConstructor) {
Component.prototype.setStatePromise = (state) => {
return new Promise<void>((resolve) => {
this.setState(state, () => {
resolve();
});
});
};
}
}

@promisifiedDecorator()
class TestComponent extends React.Component<any, any> implements IPromisifiedComponent {

}


Typescript asks to implement
setStatePromise
method: Property
setStatePromise
is missing in type
Test
. What can I do to fix this error?

Answer

The compiler complains because TestComponent is defined to implement IPromisifiedComponent but it lacks the setStatePromise method which this interface defines.
The fact that you are adding this method at runtime using the decorator is not good enough for the compiler, so you need to let it know that it's ok and you know what you're doing:

@promisifiedDecorator()
class TestComponent extends React.Component<any, any> implements IPromisifiedComponent {
    setStatePromise: (state: any) => Promise<void>;
}

Also, if your decorator doesn't need any parameters then you can simply do:

function promisifiedDecorator(Component: IPromisifiedComponentConstructor) {
    Component.prototype.setStatePromise = (state) => {
        return new Promise<void>((resolve) => {
            this.setState(state, () => {
                resolve();
            });
        });
    };
}

@promisifiedDecorator
class TestComponent extends React.Component<any, any> implements IPromisifiedComponent {
    setStatePromise: (state: any) => Promise<void>;
}
Comments