【问题标题】:Extend prototype using decorator使用装饰器扩展原型
【发布时间】:2017-03-06 04:23:08
【问题描述】:

我想添加方法setStatePromisified 来响应组件的原型,我正在尝试使用装饰器来实现:

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 要求实现 setStatePromise 方法:Test 类型中缺少属性 setStatePromise。我该如何解决这个错误?

【问题讨论】:

  • implements IPromisifiedComponent 表示您的TestComponent 需要实现IPromisifiedComponent 的方法(在您的情况下为setStatePromise)。 Typescript 无法知道你在装饰器中这样做
  • @Maxx setStatePromise 方法在装饰器内部实现
  • 我编辑了我的评论
  • @Maxx 你有什么建议吗?
  • 您可以使用setStatePromise 方法扩展React.Component 并以此扩展您的组件

标签: javascript reactjs typescript decorator


【解决方案1】:

编译器报错是因为 TestComponent 被定义为实现 IPromisifiedComponent 但它缺少此接口定义的 setStatePromise 方法。
您在运行时使用装饰器添加此方法这一事实对于编译器来说还不够好,因此您需要让它知道它没问题并且您知道自己在做什么:

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

另外,如果你的装饰器不需要任何参数,那么你可以简单地这样做:

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>;
}

【讨论】:

  • 在其他装饰器中我传递参数,所以我希望到处都有相同的签名,这就是我使用@promisifiedDecorator() 的原因。无论如何,我喜欢您的解决方案,并感谢您的解释^_^
猜你喜欢
  • 2019-07-20
  • 1970-01-01
  • 2021-07-07
  • 2016-08-18
  • 1970-01-01
  • 1970-01-01
  • 2020-06-26
  • 2016-07-18
  • 1970-01-01
相关资源
最近更新 更多