簡體   English   中英

在 typescript 中,如何使用聲明的 function 擴展全局接口

[英]In typescript how do I extend a global interface with a declared function

我正在處理一個遺留的 javascript 項目,目前正在為一些更流行的函數添加 typescript 聲明.d.ts文件,以獲得更好的 vscode 類型定義。

當前設置包括所述 function 上的多個過載,它會根據這些過載選項返回一個設定值。

declare function createChild(type: "div", options?: CreateChild_Options, node?: HTMLElement): HTMLDivElement;
declare function createChild(type: "span", options?: CreateChild_Options, node?: HTMLElement): HTMLSpanElement;
declare function createChild(type: "input", options?: CreateChild_Options, node?: HTMLElement): HTMLInputElement;

我想要的是將.createChild function 添加到返回的 HTMLElements 中。

可能它可以寫成

interface CreateChild_DivElement extends HTMLDivElement {
    createChild: createChild
}

我會用CreateChild_DivElement替換HTMLDivElement但由於聲明的 function 未正確添加到界面而失敗(工具提示將值顯示為 any)

我希望的是向 typescript 接口添加一個變量。

interface CustomElement<Original> {
   ...Original,
   createChild: createChild,
}

並像下面的例子一樣使用它

declare function createChild(type: "div", options?: CreateChild_Options, node?: HTMLElement): CustomElement<HTMLDivElement>;

顯然這是行不通的,只是一個例子。

我如何獲得聲明的.createChild function 作為返回的 HTMlElement 的一部分。

在瀏覽了一些未回答的 typescript 問題后,我遇到了一個我不知道存在的類型聲明。 我現在得到了這個完整的代碼。 有效,但它絕對不漂亮。 有沒有更好的方法來實現這一點?

export = createChild;

// Declare the functions
declare function createChild(type: "div", options?: CreateChild_Options, node?: HTMLElement): CustomElement<HTMLDivElement>;
declare function createChild(type: "span", options?: CreateChild_Options, node?: HTMLElement): CustomElement<HTMLSpanElement>;
declare function createChild(type: "input", options?: CreateChild_Options, node?: HTMLElement): CustomElement<HTMLInputElement>;
declare function createChild(type: "p", options?: CreateChild_Options, node?: HTMLElement): CustomElement<HTMLParagraphElement>;
declare function createChild(type: "a", options?: CreateChild_Options, node?: HTMLElement): CustomElement<HTMLAnchorElement>;
declare function createChild(type: "img", options?: CreateChild_Options, node?: HTMLElement): CustomElement<HTMLImageElement>;
declare function createChild(type: "ul", options?: CreateChild_Options, node?: HTMLElement): CustomElement<HTMLUListElement>;
declare function createChild(type: "li", options?: CreateChild_Options, node?: HTMLElement): CustomElement<HTMLLIElement>;
declare function createChild(type: "hr", options?: CreateChild_Options, node?: HTMLElement): CustomElement<HTMLHRElement>;
declare function createChild(type: "h1" | "h2" | "h3" | "h4" | "h5" | "h6", options?: CreateChild_Options, node?: HTMLElement): CustomElement<HTMLHeadingElement>;
declare function createChild(type: string, options?: CreateChild_Options, node?: HTMLElement): CustomElement<HTMLElement>;

type CustomElement<Original> = Original & {
    createChild: ((type: "div", options?: CreateChild_Options, node?: HTMLElement) => CustomElement<HTMLDivElement>) &
    ((type: "span", options?: CreateChild_Options, node?: HTMLElement) => CustomElement<HTMLSpanElement>) &
    ((type: "input", options?: CreateChild_Options, node?: HTMLElement) => CustomElement<HTMLInputElement>) &
    ((type: "p", options?: CreateChild_Options, node?: HTMLElement) => CustomElement<HTMLParagraphElement>) &
    ((type: "a", options?: CreateChild_Options, node?: HTMLElement) => CustomElement<HTMLAnchorElement>) &
    ((type: "img", options?: CreateChild_Options, node?: HTMLElement) => CustomElement<HTMLImageElement>) &
    ((type: "ul", options?: CreateChild_Options, node?: HTMLElement) => CustomElement<HTMLUListElement>) &
    ((type: "li", options?: CreateChild_Options, node?: HTMLElement) => CustomElement<HTMLLIElement>) &
    ((type: "hr", options?: CreateChild_Options, node?: HTMLElement) => CustomElement<HTMLHRElement>) &
    ((type: "h1" | "h2" | "h3" | "h4" | "h5" | "h6", options?: CreateChild_Options, node?: HTMLElement) => CustomElement<HTMLHeadingElement>) &
    ((type: string, options?: CreateChild_Options, node?: HTMLElement) => CustomElement<HTMLElement>);
};

type ElementNames = 'div' | 'span' | 'input' | 'p' | 'i' | 'a' | 'img' | 'ul' | 'li' | 'hr' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';


/**
 * The options for create child
 */
interface CreateChild_Options {
    id?: string,
    classList?: string[],
    style?: CSSStyleDeclaration | string,
    childNodes?: (CreateChild_Create | CreateChild_Child)[],
    on: {
        click: (this: HTMLElement, ev: MouseEvent, options: boolean | AddEventListenerOptions) => any,
        contextmenu: (this: HTMLElement, ev: MouseEvent, options: boolean | AddEventListenerOptions) => any,
        keyup: (this: HTMLElement, ev: KeyboardEvent, options: boolean | AddEventListenerOptions) => any,
        keydown: (this: HTMLElement, ev: KeyboardEvent, options: boolean | AddEventListenerOptions) => any,
        keypress: (this: HTMLElement, ev: KeyboardEvent, options: boolean | AddEventListenerOptions) => any,
        focus: (this: HTMLElement, ev: FocusEvent, options: boolean | AddEventListenerOptions) => any,
        blur: (this: HTMLElement, ev: FocusEvent, options: boolean | AddEventListenerOptions) => any,
        focusin: (this: HTMLElement, ev: FocusEvent, options: boolean | AddEventListenerOptions) => any,
        focusout: (this: HTMLElement, ev: FocusEvent, options: boolean | AddEventListenerOptions) => any,
        [key: string]: (this: HTMLElement, ev: Event, options: boolean | AddEventListenerOptions) => any,
    }
};


/**
 * Used create child to create and append a new child element
 */
interface CreateChild_Create {
    type: ElementNames,
    options?: CreateChild_Options,
}


/**
 * appends a child element that was created already
 */
interface CreateChild_Child {
    child: HTMLElement | HTMLNode
}

包含 function 聲明的文件是一個模塊。

模塊是包含一個或多個頂級importexport語句的文件。

您的文件包含

export = createChild;

使其成為一個模塊。

在模塊中以詞法方式指定的所有構造,無論它們是值還是類型,環境與否,都在該模塊的范圍內。

但是,有時我們需要從模塊中伸出一些東西到封閉的 scope 中,對於一個模塊來說,它是全局 scope。

對於值,我們照你說的做,並分配給windowglobalglobalThis的屬性。 由於 TypeScript 將類型添加到 JavaScript 它需要一種語法來使我們能夠對類型執行相同的操作。

該語法是declare global塊。

在下面的代碼中,它應用於您的示例,

export = createChild;

declare global {
  function createChild(type: "div", options?: CreateChild_Options, node?: HTMLElement): CustomElement<HTMLDivElement>;
}

暫無
暫無

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

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