将JavaScript类Mixins与TypeScript声明文件一起使用 [英] Using JavaScript Class Mixins with TypeScript Declaration Files

查看:111
本文介绍了将JavaScript类Mixins与TypeScript声明文件一起使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在声明文件中使用类mixins的帮助.具体来说,当在mixin中定义方法时,打字稿不会在混合类主体中使用它:

I need help using class mixins in declaration files. Specifically, when a method is defined in a mixin, typescript is not picking it up in the mixed class body:

就我而言,我正在应用两个mixins.第一个mixin-NotifyingElementMixin-提供了名为notify的方法,而该方法无法应用于混合类主体

In my case, I am applying two mixins. The first mixin - NotifyingElementMixin - provides a method called notify, and it's this method which is failing to apply to the mixed class body

export const NotifyingElementMixin = superclass =>
  class NotifyingElement extends superclass {
    /**
     * Fires a `*-changed` event.
     *
     * @param  {string}     propName Name of the property.
     * @param  {any} value  property value
     * @protected
     */
    notify(propName, value) {
      this.dispatchEvent(
        new CustomEvent(`${propName}-changed`, {
          detail: { value },
        })
      );
    }
  };
};

notification-element-mixin.d.ts

export declare class NotifyingElement {
  public notify(propName: string, value: any): void
}

export function NotifyingElementMixin<TBase extends typeof HTMLElement>
(superclass: TBase): TBase & NotifyingElement;

第二个mixin提供了其他属性和方法,但出于这个问题,我简化了实现

The second mixin provides other properties and methods, but for the sake of this question, I've simplified the implementation

export const ApolloQueryMixin = 
  superclass => class extends superclass {
    data = null;
    is = 'Query';
  };

apollo-query-mixin.d.ts

export declare class ApolloQuery<TCacheShape, TData, TVariables, TSubscriptionData = TData> {
  data: null
  is: string
}

type Constructor<T = HTMLElement> = new (...args: any[]) => T;
export function ApolloQueryMixin<TBase extends Constructor, TCacheShape, TData, TVariables>
(superclass: TBase): ApolloQuery<TCacheShape, TData, TVariables> & TBase;

最后,我想导出一个同时应用两个mixin并提供其自身方法的类.这是我遇到麻烦的地方

Finally, I want to export a class which applies both mixins and provides it's own methods as well. This is where I run in to trouble

class ApolloQuery extends NotifyingElementMixin(ApolloQueryMixin(HTMLElement)) {
  /**
   * Latest data.
   */
  get data() {
    return this.__data;
  }

  set data(value) {
    this.__data = value;
    this.notify('data', value);
  }
  // etc
}

apollo-query.d.ts

import { ApolloQueryMixin } from "./apollo-query-mixin";
import { NotifyingElementMixin } from "./notifying-element-mixin";

export declare class ApolloQuery<TBase, TCacheShape, TData, TVariables>
extends NotifyingElementMixin(ApolloQueryMixin(HTMLElement)) {}

当我对此进行编译或使用我的IDE时,我收到错误消息:

When I compile this, or use my IDE, i receive the error:

error TS2339: Property 'notify' does not exist on type 'ApolloQuery'.

如何将打字稿添加到混合类主体中来继承继承的方法?

How do I finagle typescript into picking up my inherited methods in the mixed class body?

推荐答案

这是我使用的mixin模式,我认为关键是返回构造函数:

Here's the mixin pattern I use, I think the key is the return constructor:

import { LitElement, property } from "lit-element";

type Constructor = new (...args: any[]) => LitElement;

interface BeforeRenderMixin {
  beforeRenderComplete: Boolean;
}

type ReturnConstructor = new (...args: any[]) => LitElement & BeforeRenderMixin;

export default function<B extends Constructor>(Base: B): B & ReturnConstructor {
  class Mixin extends Base implements BeforeRenderMixin {
    @property({ type: Boolean })
    public beforeRenderComplete: boolean = false;

    public connectedCallback() {
      super.connectedCallback();
      if (!this.beforeRenderComplete)
        this.beforeRender().then(() => (this.beforeRenderComplete = true));
    }

    public async beforeRender() {
      return;
    }

    public shouldUpdate(changedProperties: any) {
      return this.beforeRenderComplete && super.shouldUpdate(changedProperties);
    }
  }

  return Mixin;
}

它将生成:

import { LitElement } from "lit-element";
declare type Constructor = new (...args: any[]) => LitElement;
interface BeforeRenderMixin {
    beforeRenderComplete: Boolean;
}
declare type ReturnConstructor = new (...args: any[]) => LitElement & BeforeRenderMixin;
export default function <B extends Constructor>(Base: B): B & ReturnConstructor;
export {};

这篇关于将JavaScript类Mixins与TypeScript声明文件一起使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆