1

我正在尝试将 typescript 定义添加到 jasmine matcher library中。

我能够为泛型类型添加匹配器,T但现在我只想将匹配器添加到 DOM 元素。

深入研究 jasmine 类型定义代码,我发现了一种类似的方法ArrayLike(参见这里expect重载和这里ArrayLikeMatchers)。

所以我创建了一个类似的。

// Overload the expect
declare function expect<T extends HTMLElement>(actual: T): jasmine.DOMMatchers<T>;

declare namespace jasmine {
    // Augment the standard matchers. This WORKS!
    interface Matchers<T> {
        toBeExtensible(): boolean;
        toBeFrozen(): boolean;
        toBeSealed(): boolean;
        // ... other
    }
    // The matchers for DOM elements. This is NOT working!
    interface DOMMatchers<T> extends Matchers<T> {
        toBeChecked(): boolean;
        toBeDisabled(): boolean;
    }
}

但是,不工作:(

给定以下代码:

const div = document.createElement("div");
expect(div).toBeChecked();

类型检查器给了我错误:

[js]“匹配器”类型上不存在属性“toBeChecked”。


唯一的解决方案似乎是在核心 jasmine 库中的泛型之前(在此处重载之后)添加expect重载。expectArrayLike

但是......这是不可行的:)

关于如何正确实施有效解决方案的任何提示?

4

1 回答 1

2

问题是 Typescript 按声明顺序选择重载,并且非常通用的declare function expect<T>(actual: T): jasmine.Matchers<T>;将出现在您的重载之前。您可能可以使用///引用找到一些神奇的排序,但我无法让它工作,而且它会非常脆弱。

更好的方法是直接添加您的额外功能,Matchers<T>但限制thisMatchers<HTMLElement>

declare namespace jasmine {
    interface Matchers<T> {
        toBeExtensible(): boolean;
        toBeFrozen(): boolean;
        toBeSealed(): boolean;

        // this must be derived from Matchers<HTMLElement>
        toBeDisabled(this: Matchers<HTMLElement>): boolean;
        // or make it generic, with T extending HTMLElement if you really need the actual type for some reason 
        toBeChecked<T extends HTMLElement>(this: Matchers<HTMLElement>): boolean; 
    }
}

// usage
const div = document.createElement("div");
expect(div).toBeChecked(); // ok
expect(10).toBeChecked() // error
于 2018-04-10T10:53:14.390 回答