【发布时间】:2020-07-21 09:43:44
【问题描述】:
我正在处理一个遗留的 javascript 项目,目前正在为一些更流行的函数添加 typescript 声明 .d.ts 文件,以获得更好的 vscode 类型定义。
当前设置包括对所述函数的多个重载,它会根据这些重载选项返回一个设定值。
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 函数添加到返回的 HTMLElements 中。
可以写成
interface CreateChild_DivElement extends HTMLDivElement {
createChild: createChild
}
我会用CreateChild_DivElement 替换HTMLDivElement,但由于声明的函数没有正确添加到界面而失败(工具提示显示任何值)。
我希望为打字稿界面添加一个变量。
interface CustomElement<Original> {
...Original,
createChild: createChild,
}
并像下面的例子一样使用它
declare function createChild(type: "div", options?: CreateChild_Options, node?: HTMLElement): CustomElement<HTMLDivElement>;
显然这是行不通的,只是一个例子。
如何将声明的 .createChild 函数作为返回的 HTMlElement 的一部分。
在浏览了一些未回答的打字稿问题后,我发现了一个我不知道存在的类型声明。我现在得到了这个完整的代码。有效,但它绝对不漂亮。有没有更好的方法来实现这一点?
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
}
【问题讨论】:
-
在一个模块中,一个包含顶级
import或export的文件,所有声明都限定在该模块的范围内。为了在模块中声明像createChild这样的环境全局变量,TypeScript 提供了declare global构造。例如:import x from 'y'; declare global { function createChild(type: "div", ...) } -
@AluanHaddad 我似乎听不懂你在说什么。我认为声明一个全局是向窗口/全局范围添加一个变量。在这种情况下,我似乎无法弄清楚如何使用全局变量。
-
我举个例子
标签: typescript typescript-typings