在类型转换为TypeScript的变量上调用`new`

时间:2019-06-14 18:31:10

标签: typescript jestjs

我正在编写一些单元测试,我想测试我的构造函数在运行时失败,并带有无效的参数。如果在TS项目中使用无效参数调用了构造函数,则构造函数将在编译时失败,因此我必须首先将其强制转换为any

my-class.ts

export default class MyClass {
    constructor(public value: 1 | 2 | 3) {
        if (!this.value || 
            isNaN(this.value) || 
            this.value < 1 || this.value > 3 || 
            parseInt(this.value) !== this.value) {
            throw new Error(`Invalid value: '${this.value}'`);
        }
    }
}

my-class.test.ts

test('MyClass validates its constructor arguments', () => {
    expect(() => new (MyClass as any)()).toThrowErrorMatchingSnapshot();
    expect(() => new (MyClass as any)('abc')).toThrowErrorMatchingSnapshot();
    expect(() => new (MyClass as any)(null)).toThrowErrorMatchingSnapshot();
    // ...
});

我想清理这个问题,因此我只能通过设置局部变量来进行强制转换。

test('MyClass validates its constructor arguments', () => {
    // this type declaration isn't right
    const MC = MyClass as any as { new: (...args: any[]) => MyClass };

    expect(() => new MC()).toThrowErrorMatchingSnapshot();
    expect(() => new MC('abc')).toThrowErrorMatchingSnapshot();
    expect(() => new MC(null)).toThrowErrorMatchingSnapshot();
    // ...
});

我模糊地记得写过一个泛型,该泛型的类型参数期望一个类,而我认为这就是我的写法-一个具有new函数的对象,但是现在找不到我在哪里在网络上找到了它,我什至都不记得我最初写的是哪个项目。

无论如何,TypeScript用此代码对我大喊:

  

不能对类型缺少调用或构造签名的表达式使用'new'。ts(2351)

我还尝试将{ new: ... }更改为{ constructor: ... },结果相同。

我可以将MC保留为any,这对于单元测试很合适,但是我想知道将来如何做。

2 个答案:

答案 0 :(得分:2)

test('MyClass validates its constructor arguments', () => {

    type Constructor<T> = new (...args: any[]) => T;
    const MC = MyClass as Constructor<MyClass>;

    expect(() => new MC()).toThrowErrorMatchingSnapshot();
    expect(() => new MC('abc')).toThrowErrorMatchingSnapshot();
    expect(() => new MC(null)).toThrowErrorMatchingSnapshot();
    // ...
});

也可以内联执行此操作,尽管使用解释变量似乎更清楚。

const MC = MyClass as new (...args: any[]) => MyClass;

这里是both options in the playground

答案 1 :(得分:1)

结果证明我很近。 TypeScript作者为这种声明选择了一种怪异的语法,但我不能坦白地说我可以提出更好的建议。

const MC = MyClass as any as new(...args[]: any[]) => MyClass;