打字稿 - 继承静态属性没有静态关键字

Typescript - inheriting static properties without static keyword

我有多个 class 代表数据库中的实体。

abstract class Entity {
    static columns: Column[];
    static showInNav: boolean;
    static dependencies: string[];
    // non-static fields
}
class Entity_A extends Entity {
    //static properties redeclaration
    //non-static properties
}
class Entity_B extends Entity {
    //static properties redeclaration
    //non-static properties
}

每个 class 扩展实体或其子项之一。 在初始化阶段,我将 classes 放入数组 [Entity_A, Entity_B, ...] 中,遍历它们并读取它们的属性以了解如何设置应用程序。静态属性基本上是我的配置。

问题是,typescript 中没有静态契约,这使得它很容易出错,而且很难找到它(而且我读过这通常不是一个好的做法)。 我可以将静态属性更改为方法并简单地执行 new currentClass().property。 但我相信一定有更好的方法。

有什么想法吗?

编辑(我真正想要的): 我希望能够在 classes 中安全地定义 "configuration"(类型检查 + 强制覆盖)并在给定 类

数组时轻松访问它

您可以在模块中隐藏实际的 Entity class(不导出它),并且只导出一个函数,该函数将所需的静态字段作为参数。此函数将 return 从隐藏基数 class 派生的 class 并将覆盖静态字段。此函数的结果将用作派生实体的基础 class:

entity.ts

abstract class EntityImpl {
    static columns: Column[];
    static showInNav: boolean;
    static dependencies: string[];
    abstract doStuff(): void;
}
export interface Column {
    // Dummy for this sample
}

export function Entity(required: { columns: Column[]; showInNav: boolean; dependencies: string[];}) {
    abstract class Entity  extends EntityImpl {
        static columns: Column[] = required.columns
        static showInNav: boolean = required.showInNav;
        static dependencies: string[] = required.dependencies;
    }
    return Entity;
}
// Export a type definition so we can use the base type as needed 
export type Entity = EntityImpl;
// Export a type definition that represents the type, so we can access all the static props 
export type EntityClass = typeof EntityImpl;

impl.ts

import { Entity, EntityClass } from './entity'

class Entity_A extends Entity({
    columns: [],
    dependencies: [],
    showInNav: true
}) {
    doStuff(): void {} //abstract methids HAVE to be imlementes as expected
}

class Entity_B extends Entity({
    columns: [],
    dependencies: [],
    showInNav: false
}) {
    doStuff(): void {}
}

// Array of types, with save access
var allClasses : Array<EntityClass> = [Entity_A, Entity_B];
for(let type of allClasses) {
    console.log(type.showInNav);
}

// Array of instances, with save access
var data: Array<Entity> = [new Entity_A(), new Entity_B()];
data.forEach(x => x.doStuff());

这种方法使字段保持静态,并强制实施者指定它们。据我所知,诸如强制您实现抽象方法等功能也很有效。

如果你需要一个派生实体的 class 但它是其他 class 的基础 class 你可以应用相同的模式,即将它封装在一个函数中并使用作为基础的函数 class.