Class 通过求值参数为新类键入脚本

Class 通过求值参数为新类键入脚本,class,typescript,decorator,evaluate,Class,Typescript,Decorator,Evaluate,我可以有一个函数(或方法上的装饰器)来评估传入类并生成新类,同时删除所有第一个参数,这样我就可以使用新类进行扩展,还是不能使用新类来进行扩展 您可以使用类似的方法来实现这一点。您需要替换构造函数的返回类型,并使用映射类型创建忽略第一个参数的新函数: class A { public aCall(a: any, payload: string) {} public bCall(a: any, payload: number) {} public cCall(a: any) {}

我可以有一个函数(或方法上的装饰器)来评估传入类并生成新类,同时删除所有第一个参数,这样我就可以使用新类进行扩展,还是不能使用新类来进行扩展

您可以使用类似的方法来实现这一点。您需要替换构造函数的返回类型,并使用映射类型创建忽略第一个参数的新函数:

class A {
   public aCall(a: any, payload: string) {}
   public bCall(a: any, payload: number) {}
   public cCall(a: any) {}
   .
   .
   .
}

function createNewClass(aCtor: A) {
  // load all of the A method and remove first params
  // generic code on here
  // Final result should be like this
  return class B {
    public aCall(payload: string) {}
    public bCall(payload: number) {}
  }
}

// C.d.ts
interface C extends createNewClass(A) {}
这不仅缩短了时间,而且解决了许多问题

  • 可选参数仍然是可选的
  • 参数名被保留
  • 适用于任意数量的参数

    • 如果出于某种原因,您关心实际尝试实现此功能,您可以执行以下操作。注意,我只将用两个参数替换方法。如果您需要执行所有方法,则键入必须更加详细,如@TitianCernicova Dragomir的回答:

      type IsValidArg<T> = T extends object ? keyof T extends never ? false : true : true;
      
      type ArgumentTypes<T> = T extends (... args: infer U ) => any ? U: never;
      type ReplaceInstanceType<T, TNewInstance> = T extends new (...args: any[])=> infer R ? new (...a: ArgumentTypes<T>) => TNewInstance : never;
      
      type ArgumentTypesSkipOne<T> = T extends (a: any, ... args: infer U ) => any ? U: never;
      type RemoveArg<T> = T extends (a: any, ...args: any[])=> infer R ? (...a: ArgumentTypesSkipOne<T>) => R : T;
      
      type RemoveFirstArg<TCtor extends new (... args: any[]) => any > = ReplaceInstanceType<TCtor,  { [P in keyof InstanceType<TCtor>]: RemoveArg<InstanceType<TCtor>[P]> }>
      
      function createNewClass<TCtor extends new (... args: any[]) => any >(aCtor: TCtor) : RemoveFirstArg<TCtor>{
          // load all of the A method and remove first params
          return null as any;
      }
      
      在使用这样的类玩游戏时,可能会有各种各样的警告,所以要小心,真正了解用例,以及当遇到不符合用例的行为时会发生什么


      希望有帮助。祝你好运

      我想你想要一个通用的版本吗?是的,这样我就可以替换任何传入的类。它们只是在类型中插入的?还是要为创建的类
      B
      实现?因为在实现中可能有不同的选项..仅限于类型。我只想让我的接口C扩展经过处理的类带,实际上我将在声明文件(d.ts)上使用它,然后您可以将
      protoVal.length==2
      更改为
      protoVal.length=R?(有效载荷:P)=>R:T[K]
      to
      T[K]扩展(a:any,payload:inferp)=>inferr?(有效载荷:P)=>R:T[K]扩展(a:any)=>推断R?()=>R:T[K]}谢谢你的帮助谢谢一吨提香!我最终创建了一个基于此的库
      
      type IsValidArg<T> = T extends object ? keyof T extends never ? false : true : true;
      
      type ArgumentTypes<T> = T extends (... args: infer U ) => any ? U: never;
      type ReplaceInstanceType<T, TNewInstance> = T extends new (...args: any[])=> infer R ? new (...a: ArgumentTypes<T>) => TNewInstance : never;
      
      type ArgumentTypesSkipOne<T> = T extends (a: any, ... args: infer U ) => any ? U: never;
      type RemoveArg<T> = T extends (a: any, ...args: any[])=> infer R ? (...a: ArgumentTypesSkipOne<T>) => R : T;
      
      type RemoveFirstArg<TCtor extends new (... args: any[]) => any > = ReplaceInstanceType<TCtor,  { [P in keyof InstanceType<TCtor>]: RemoveArg<InstanceType<TCtor>[P]> }>
      
      function createNewClass<TCtor extends new (... args: any[]) => any >(aCtor: TCtor) : RemoveFirstArg<TCtor>{
          // load all of the A method and remove first params
          return null as any;
      }
      
      type RemoveFirstArgOfTwoArgMethods<T> = { [K in keyof T]:
        T[K] extends (a: any, payload: infer P) => infer R ? (payload: P) => R : T[K];
      }
      
      function createNewClass<T>(aCtor: new (...args: any[]) => T): new (...args: any[]) => RemoveFirstArgOfTwoArgMethods<T> {
      
        const B = (class extends (aCtor as any) {}) as new (...args: any[]) => RemoveFirstArgOfTwoArgMethods<T>;
      
        // you will need to actually decide what that first argument will be
        const firstVal: any = "whoKnows";
      
        Object.keys(aCtor.prototype).forEach(k => {
          const protoVal = (aCtor.prototype)[k];
          if ((typeof protoVal === 'function') && (protoVal.length === 2)) {
            B.prototype[k] = function (...args: any[]) { return (protoVal as Function).call(this, firstVal, ...args) }
          }
        })
      
        return B;
      }
      
      class A {
        public aCall(a: any, payload: string) {
          console.log("aCall(" + a + "," + payload + ")");
        }
      }
      
      const a = new A();
      a.aCall("explicit", "call"); // aCall(explicit, call);
      
      const C = createNewClass(A);
      const c = new C();
      c.aCall("implicit"); // aCall(whoKnows, implicit);