如何让typescript了解动态添加到类中的静态成员的存在?

如何让typescript了解动态添加到类中的静态成员的存在?,typescript,Typescript,我有一个QueryBuilder,我想在Model类中以静态成员的形式展示它的所有方法 显然,这是有效的Javascript代码。然而,我怎样才能让typescript理解模型上存在的那些静态方法呢 function queryable (target: any) { for (const prop in target.prototype.builder) { if (prop === 'constructor' || target.prototype.hasOwnProperty(

我有一个
QueryBuilder
,我想在
Model
类中以静态成员的形式展示它的所有方法

显然,这是有效的Javascript代码。然而,我怎样才能让typescript理解
模型上存在的那些静态方法呢

function queryable (target: any) {
  for (const prop in target.prototype.builder) {
    if (prop === 'constructor' || target.prototype.hasOwnProperty(prop)) {
      continue;
    }
    target[prop] = (...args: any[]): any => {
      return target.prototype.builder[prop](...args);
    };
  }
}

class QueryBuilder {
  where(prop: string, value: string) {
    console.log(prop, value);
    console.log("I've presented on model class as static method.");
  }
  // ...
}

@queryable
class Model {
  get builder () {
    return new QueryBuilder();
  }
  // ...
}


// calling static where
Model.where('color', 'red');
类型“typeof Model”上不存在属性“where”


请参见

中的内容,因为Typescript是一种强大的键入语言,所以它总是检查类型用法是否与类型接口匹配。当Typescript不知道您要添加一个新方法时,这种检查会在传输过程中进行。因为您是在运行时添加它的。调用这样一个方法的唯一方法是将其转换为像
any

(<any>Model).where('color', 'red');
(型号)。其中('color','red');

这就像你对Typescript说,你确信方法的存在,transpiller不应该担心它。

你应该注意的问题是,到目前为止(3.5.1),装饰器无法更改它所装饰的类的类型

也就是说,您仍然可以以相同的方式定义decorator,但是显式地调用它,而不是作为decorator,正如许多使用redux流行的
connect
decorator的typescript项目所做的那样

class _Model {
  get builder () {
    return new QueryBuilder();
  }

  // ...
}
const Model = queryable(_Model);
或者,如果它是模块的主要导出,您可以使用一个名称:

class Model {
  get builder () {
    return new QueryBuilder();
  }

  // ...
}
export default queryable(Model);
然后,诀窍是更好地为装饰程序添加注释,以教授typescript对其
目标所做的所有添加
queryable

function queryable<T extends new (...args: any[]) => {builder: any}>(target: T): InstanceType<T>['builder'] & (typeof target) {
  for (const prop in target.prototype.builder) {
    if (prop === 'constructor' || target.prototype.hasOwnProperty(prop)) {
      continue;
    }
    (target as any)[prop] = (...args: any[]): any => {
      return target.prototype.builder[prop](...args);
    };
  }
  return target as any
}
函数可查询{builder:any}>(目标:T):InstanceType['builder']&(typeof目标){
for(target.prototype.builder中的常量属性){
if(prop=='constructor'| | target.prototype.hasOwnProperty(prop)){
继续;
}
(目标为任意)[prop]=(…args:any[]):any=>{
返回target.prototype.builder[prop](…args);
};
}
返回任何目标
}

好的观点。我不介意显式实现。然而,实际上,
模型
类也接受一种类型,即,
类模型扩展…
,我想知道在调用
queryable(Model)
的示例中如何解决这种情况?这应该没有问题。参数的类型只是一个具有生成器属性的类。返回类型表示它是同一类加上生成器字段。+1。因此,在这里解决我的原始问题,帮助Typescript理解动态添加的静态成员将是一个连接器,如
const connect={builder:any}>(target:T):InstanceType['builder']&(typeof target)=>target然后<代码>常量模型=连接(原始模型)