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]
toT[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);