打字稿基类参考子类

时间:2018-11-20 13:22:52

标签: typescript

我正在尝试创建具有以下继承关系的树状结构:

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
  }
}

2 个答案:

答案 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.tssub.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();