簡體   English   中英

使用 JavaScript Class Mixins 與 TypeScript 聲明文件

[英]Using JavaScript Class Mixins with TypeScript Declaration Files

我需要幫助在聲明文件中使用 class mixins。 具體來說,當在 mixin 中定義方法時,typescript 不會在混合的 class 主體中提取它:

就我而言,我正在應用兩個 mixin。 第一個 mixin - NotifyingElementMixin - 提供了一個名為notify的方法,正是這種方法無法應用於混合 class 主體

通知元素mixin.js

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

通知元素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提供了其他屬性和方法,但是為了這個問題,我簡化了實現

阿波羅查詢mixin.js

export const ApolloQueryMixin = 
  superclass => class extends superclass {
    data = null;
    is = '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;

最后,我想導出一個 class 應用兩個 mixins 並提供它自己的方法。 這是我遇到麻煩的地方

阿波羅查詢.js

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

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

阿波羅查詢.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 時,我收到錯誤:

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

如何讓 typescript 在混合 class 主體中獲取我繼承的方法?

這是我使用的mixin模式,我認為關鍵是返回構造函數:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM