【问题标题】:Typescript base class reference subclassTypescript 基类引用子类
【发布时间】:2018-11-20 13:22:51
【问题描述】:

我正在尝试创建一个具有如下继承的树状结构:

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

【问题讨论】:

    标签: typescript


    【解决方案1】:

    试试这个:

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

    【讨论】:

    • 这里的主要问题是subclassChildrenBaseClass 上不再可用。由于children 仍然是BaseClass 的数组,因此需要大量转换。
    • 这样呢?
    • 这将过滤掉子类但不再强制转换它们,我得到的不再是SubClass[],而是BaseClass[]
    【解决方案2】:

    使用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();
    

    【讨论】:

      猜你喜欢
      • 2020-07-16
      • 1970-01-01
      • 1970-01-01
      • 2020-07-17
      • 1970-01-01
      • 2017-07-07
      • 2017-06-24
      • 2018-04-21
      相关资源
      最近更新 更多