Jasmine自定义匹配器类型定义

时间:2018-04-10 10:25:40

标签: typescript jasmine matcher type-definition jasmine-matchers

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

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

深入研究茉莉花类型定义代码我发现了ArrayLike的类似方法(expect重载请参阅hereArrayLikeMatchershere

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

// 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'在'Matchers'类型中不存在。

唯一的解决方案似乎是在核心expect之前添加expect重载 <{1}}(在ArrayLike重载here之后)茉莉花库。

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

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

1 个答案:

答案 0 :(得分:2)

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

更好的方法是在Matchers<T>上添加额外的功能,但约束this来自Matchers<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