我正在编写一些单元测试,我想测试我的构造函数在运行时失败,并带有无效的参数。如果在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
,这对于单元测试很合适,但是我想知道将来如何做。
答案 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;
答案 1 :(得分:1)
结果证明我很近。 TypeScript作者为这种声明选择了一种怪异的语法,但我不能坦白地说我可以提出更好的建议。
const MC = MyClass as any as new(...args[]: any[]) => MyClass;