Typescript 从继承的类定义动态生成的属性

Typescript 从继承的类定义动态生成的属性,typescript,typescript-definitions,.d.ts,Typescript,Typescript Definitions,.d.ts,我正在尝试为我的项目生成d.ts声明文件 有两个类计算重逻辑,其余的类继承自它们。子类的属性不是在对象本身上定义的,而是在类中名为defaults的getter上定义的,并在运行时定义 基本型号 abstract class BaseModel {} abstract class Model extends BaseModel {} 继承模型 class Example extends Model { get defaults() { return {

我正在尝试为我的项目生成
d.ts
声明文件

有两个类计算重逻辑,其余的类继承自它们。子类的属性不是在对象本身上定义的,而是在类中名为
defaults
getter上定义的,并在运行时定义

基本型号

abstract class BaseModel {}
abstract class Model extends BaseModel {}
继承模型

class Example extends Model {
    get defaults() {
       return {
            someProp: 1,
            anotherProp: 2
       }
    }
}
我的代码工作得很好,但是动态添加的属性没有自动完成功能。我尝试将以下内容添加到
d.ts
文件中,以使其了解动态属性,但似乎不起作用

索引d.ts

class Model<T> extends BaseModel {
    [P in keyof T]: T[P]
}

type ExampleType = {
    someProp : number
    anotherProp : number
}

class Example extends Model<ExampleType> {}
类模型扩展了BaseModel{
[P in keyof T]:T[P]
}
类型示例示例类型={
someProp:数字
另一个属性:数字
}
类示例扩展了模型{}

如何将属性定义添加到继承的类中而不必手动定义它们?

您不能直接执行此操作,如果您使用一个额外的函数创建类,该函数将改变创建类以添加项目,则可以执行此操作:

type ReplaceInstanceType<T extends new (...args: any[])=> any, TNewInstance> = 
    T extends new (...args: infer U)=> any ? 
        new (...args: U) => TNewInstance : 
        never;

function createModel<T extends new (...args: any[])=> any>(modelClass: T) : 
    ReplaceInstanceType<T, InstanceType<T> & InstanceType<T>['defaults']> {
    return modelClass as any;
}
这样做的缺点是,额外的字段不能从类本身中使用,这在某些情况下可能是一个问题

第二种用法是在新类的extends子句中使用
createModel
,只在传递给extends的类中定义默认值,在外部类中添加额外的方法:

class Example extends createModel(class extends Model {
    get defaults() {
        return {
            someProp: 1,
            anotherProp: 2
        }
    }
}) {
    constructor(data: string) {
        super();
        this.anotherProp // new properties are accesible
    }
};
new Example(``).anotherProp // we can create the class and access the extra fields
new Example("").someProp
这种方法的缺点是实际上创建了两个类:外部类是我们实际使用的,内部类是我们用来添加defaults属性的

编辑

由于Type Script实际上在键入和验证键名方面做得很好,您也可以考虑使用<代码> GET/SET/<代码>方法,您可以获得良好的代码完成和类型验证,但它有点冗长:

abstract class BaseModel { 
    abstract get defaults();
    get<K extends keyof this['defaults']>(name: keyof this['defaults']): this['defaults'][K]{
        return this[name] as any;
    }
    set<K extends keyof this['defaults']>(name: keyof this['defaults'], value:  this['defaults'][K]) : void{
        this[name] =  value;
    }
}

class Example extends BaseModel {
    get defaults() {
        return {
            someProp: 1,
            anotherProp: 2
        }
    }

};
new Example().get('anotherProp')
new Example().get("someProp") 
new Example().set("someProp", 1) // 
new Example().set("someProp", "1") // error wrong type
new Example().get("someProp2")  // error
抽象类基模型{
抽象获取默认值();
get(name:keyof this['defaults']):this['defaults'][K]{
将此[名称]作为任何名称返回;
}
集合(名称:keyof this['defaults'],值:this['defaults'][K]):void{
此[名称]=值;
}
}
类示例扩展了BaseModel{
获取默认值(){
返回{
一些建议:1,
另一项建议:2
}
}
};
新示例().get('anotherProp')
新示例().get(“someProp”)
新示例().set(“someProp”,1)//
新示例().set(“someProp”,“1”)//错误类型
新示例().get(“someProp2”)//错误
abstract class BaseModel { 
    abstract get defaults();
    get<K extends keyof this['defaults']>(name: keyof this['defaults']): this['defaults'][K]{
        return this[name] as any;
    }
    set<K extends keyof this['defaults']>(name: keyof this['defaults'], value:  this['defaults'][K]) : void{
        this[name] =  value;
    }
}

class Example extends BaseModel {
    get defaults() {
        return {
            someProp: 1,
            anotherProp: 2
        }
    }

};
new Example().get('anotherProp')
new Example().get("someProp") 
new Example().set("someProp", 1) // 
new Example().set("someProp", "1") // error wrong type
new Example().get("someProp2")  // error