我有以下示例接口/类
export interface MyErrorI {
something: boolean;
}
export class MyError extends Error implements MyErrorI {
public something = false;
constructor(message: string, key: keyof MyErrorI ) {
super(message);
this[key] = true; // this is the code that I want to reuse
}
}
概念是构造函数根据其关键参数设置其属性的值。
现在我想用另一个类来扩展它:
interface MyNewErrorI extends MyErrorI {
somethingElse: boolean;
}
export class MyNewError extends MyError implements MyNewErrorI {
public somethingElse = false;
constructor(message: string, key: keyof MyNewErrorI) {
super(message, key);
}
}
现在,键参数可以具有扩展MyErrorI
的接口的属性。由于我实际问题的复杂性,我不想将代码从父类的构造函数复制/粘贴到子类的构造函数。
但是,上面的代码无法正常工作,因为MyError
的构造函数需要键MyErrorI
。但是,键somethingElse
是MyNewError
的有效属性。
因此,问题是:父类的构造函数是否有可能每次基于其子类调用key
来访问super
参数? < / p>
我试图做这样的事情,但是它也不起作用:
export class MyError<T extends PaymentErrorI> extends Error implements MyErrorI {
public something = false;
constructor(message: string, key: keyof T) {
super(message);
this[key] = true;
}
}
实际的构造函数如下:
constructor(message: string, key: keyof MyErrorI | Array<keyof MyErrorI>, data?: any) {
super(message);
if (key instanceof Array) {
key.forEach((v) => {
this[v] = true;
});
} else {
this[key] = true;
}
this.payload = data;
}
因此,使用super(message, key, data)
进行调用可以节省更多的代码行,并使其更易于维护。
或者,我可以使用功能相同的功能吗? 像
const setKeys = <T>(err: T, key: keyof T | Array<keyof T>)
将提供所需的功能。这样,err[key] = true
我得到Type 'true' is not assignable to type 'T[keyof T]'
谢谢!
答案 0 :(得分:1)
与构造函数分离的函数可能是可行的方法,因为构造函数无法覆盖预期的this
类型或使用特殊的this
类型来引用要创建的子类的类型构造,并且仅仅为了进行键设置而添加类型参数将非常笨拙。函数签名的问题在于,您尚未确保传入的T
的键具有布尔值,因此将true
分配给它们可能无效。函数定义应如下所示:
const setKeys = <K extends keyof any>(err: {[P in K]: boolean}, key: K | Array<K>) => {
if (key instanceof Array) {
key.forEach((v) => {
err[v] = true;
});
} else {
err[key] = true;
}
};
或者您可以将setKeys
设为MyError
的方法,因为方法(不同于构造函数)可以覆盖预期的this
类型:
export class MyError extends Error implements MyErrorI {
// ...
setKeys<K extends keyof any>(this: { [P in K]: boolean }, key: K | Array<K>) {
if (key instanceof Array) {
key.forEach((v) => {
this[v] = true;
});
} else {
this[key] = true;
}
}
}