我正在尝试创建具有以下继承关系的树状结构:
base.ts
:
export class BaseClass {
children: BaseClass[] = [];
get subclassChildren(): SubClass[] {
return this.children.filter((child): child is SubClass => child instanceof SubClass);
}
}
sub.ts
:
import { BaseClass } from './base';
export class SubClass extends BaseClass {}
这不会起作用,因为基类找不到SubClass
:
TSError: ⨯ Unable to compile TypeScript: base.ts(4,26): error TS2304: Cannot find name 'SubClass'. base.ts(5,49): error TS2304: Cannot find name 'SubClass'. base.ts(5,78): error TS2304: Cannot find name 'SubClass'.
这并不意外,但是如果我尝试在base.ts
中导入子类,则由于彼此之间都有循环引用,因此它也将不起作用:
TypeError: Object prototype may only be an Object or null: undefined
是否有转发声明SubClass
的方法或使此代码正常工作的其他方法?
编辑:
tsconfig.json
(由tsc --init
生成):
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"strict": true,
"esModuleInterop": true
}
}
答案 0 :(得分:0)
尝试一下:
base.ts:
export class BaseClass {
className = "base"
children: BaseClass[] = [];
get subclassChildren() {
return this.children.filter((child) => { return child.className == "subClass" });
}
}
sub.ts:
import { BaseClass } from './base';
export class SubClass extends BaseClass {
className = "subClass"
}
答案 1 :(得分:0)
使用module augmentation可以向现有类添加方法和属性:
base.ts
:
export class BaseClass {
children: BaseClass[] = [];
}
sub.ts
:
import { BaseClass } from './base';
export class SubClass extends BaseClass {
foo(){
console.log('foo');
}
}
/* augment base class */
declare module "./base" {
interface BaseClass {
subclassChildren: SubClass[];
bar(): void;
}
}
/* implement getter */
Object.defineProperty(BaseClass.prototype, 'subclassChildren', {
get(){
return this.children.filter((child: BaseClass): child is SubClass => child instanceof SubClass);
},
});
/* implement method */
BaseClass.prototype.bar = function bar(){
console.log('bar');
}
使用它时,base.ts
和sub.ts
都必须导入,因为只有sub.ts
包含增强类:
import { BaseClass } from './base';
import { SubClass } from './sub';
const root = new BaseClass();
root.children.push(new BaseClass());
root.children.push(new SubClass());
root.subclassChildren.map((child) => child.foo());
root.bar();