【问题标题】:Extending type definition in variable defined in lib.d.ts在 lib.d.ts 中定义的变量中扩展类型定义
【发布时间】:2018-02-14 22:01:29
【问题描述】:

我有使用 mootools 进行转换的遗留代码。 Mootools 引入了一个新的带有两个参数的“元素”构造函数。我没有找到任何mootools的类型定义文件,所以我必须自己写。

typescript 标准库 (lib.d.ts) 定义 Element 如下:

  var Element: { prototype: Element; new(): Element; };

这使得无法扩展现有接口。

我显然在尝试的是

interface Element {
        new(s: string, s2: any): Element;
}

但是,编译器仍然抱怨

var c = new Element('p',{});

作为the contructor expected 0 arguments, but got 2。这里首选的解决方法是什么?


mootools 构造函数

var Element = this.Element = function(tag, props){
    var konstructor = Element.Constructors[tag];
    if (konstructor) return konstructor(props);
    if (typeof tag != 'string') return document.id(tag).set(props);

    if (!props) props = {};

    if (!(/^[\w-]+$/).test(tag)){
        var parsed = Slick.parse(tag).expressions[0][0];
        tag = (parsed.tag == '*') ? 'div' : parsed.tag;
        if (parsed.id && props.id == null) props.id = parsed.id;

        var attributes = parsed.attributes;
        if (attributes) for (var attr, i = 0, l = attributes.length; i < l; i++){
            attr = attributes[i];
            if (props[attr.key] != null) continue;

            if (attr.value != null && attr.operator == '=') props[attr.key] = attr.value;
            else if (!attr.value && !attr.operator) props[attr.key] = true;
        }

        if (parsed.classList && props['class'] == null) props['class'] = parsed.classList.join(' ');
    }

    return document.newElement(tag, props);
};



// Browser
  var Browser = this.Browser = parse(navigator.userAgent, navigator.platform);




if (Browser.Element){
    Element.prototype = Browser.Element.prototype;
    // IE8 and IE9 require the wrapping.
    Element.prototype._fireEvent = (function(fireEvent){
        return function(type, event){
            return fireEvent.call(this, type, event);
        };
    })(Element.prototype.fireEvent);
}

【问题讨论】:

  • 这是否意味着无法为 mootools 库编写正确的类型定义文件?
  • 您需要省略 Dom 的声明并使用一组自定义声明。 mootools 是否真的替换了浏览器中的 element 内置对象?这太可怕了。
  • 我把mootools构造函数的定义放在问题里
  • 你能指出实际上覆盖 window.Element 的 mootools 的 JavaScript 吗?
  • 它是 Browser.Element,我刚刚添加了它

标签: typescript


【解决方案1】:

你不需要扩展Element接口,你需要扩展Element变量的类型。这有点令人困惑,从 TS 的角度来看,这是两个独立的实体。你可以这样做:

declare const Element: { // If you do that in a .d.ts file, you don't need declare.
    prototype: Element; // Element here is interface, we leave it unchanged.
    new(): Element; // Standard constructor.
    new(s: string, n: number): Element; // Your custom constructor.
};

const e = new Element('1', 2);

e.nodeName; // => string, i.e. result object implements Element interface.

【讨论】:

  • 如果我在 .d.ts 文件中这样做,无论我是否添加“声明”,投诉者都会抱怨后续的变量声明。但是 - 有效的是:我将 'declare const' 替换为 'var' 并将定义放在 .ts 文件的顶部我实际上使用了 new Element('1',2) 构造函数
  • 这意味着。我很高兴,但如果有一种方法可以通过仅修改 .d.ts 文件来实现,我会更高兴。
  • 我理解你的意思,但你应该指出Element在类型位置和值位置上是不同的。
  • 对于可扩展声明,类型将是另一个接口,但由于它是匿名类型文字,因此无法扩展。我相信这是故意的,因为像添加一个新的构造函数这样的事情没有任何意义,因为我们不能在运行时替换 Element 函数对象
  • 从这个意义上说,'Element' 是一个内置类的名称以及一个类型(在 Typescript 意义上),不是吗?
猜你喜欢
  • 2021-01-14
  • 1970-01-01
  • 1970-01-01
  • 2013-05-22
  • 1970-01-01
  • 2019-03-05
  • 2018-09-02
  • 1970-01-01
相关资源
最近更新 更多