Typescript:泛型类的换行函数返回类型



我无法用Typescript的通用方式来解决这个问题,我将非常感谢任何帮助!

  • 工厂应该部署一个合约
  • 一个CustomFactory是一个工厂,应该部署一个CustomContract(这是一个合同)
  • MockFactory应该是所有这些逻辑的包装器

像这样的东西将是目标(半伪代码)

interface MockFactory<F extends Factory> extends F {
deploy: (...args: Parameters<F.prototype.deploy>) => MockContract<F.prototype.deploy.returnValue>
}

为了更好地说明这个问题,我创建了一个Playground,在这里你可以看到错误

仅通过使用ReturnType和Parameters解决,还需要将接口转换为类型:

interface Contract {}
interface Factory {
deploy: (...args: any[]) => Contract;
}
class CustomContract implements Contract {}
class CustomFactory implements Factory {
deploy(x: number, y: number): CustomContract {
return {};
}
}
type MockContract<C extends Contract> = Contract & C & {
mockProperty: number;
}
type MockFactory<F extends Factory> = F & {
// deploy should have the parameters of the function deploy inside F (in this case CustomFactory)
// deploy should return a MockContract of the return type of the function deploy inside F (MockContract<CustomContract> in a generic way)
deploy: (...args: Parameters<F['deploy']>) => MockContract<ReturnType<F['deploy']>>
}
const example: MockFactory<CustomFactory> = {} as any;
example.deploy(1, 2);

更新操场

您可以使用(抽象)类,但也可以使用接口。在这种情况下,让工厂本身变得通用似乎是错误的举动。将契约类型改为泛型。经过一段时间的尝试,我能够将这些内容拼在一起:

interface Contract { }
interface Factory<A extends any[], C extends Contract> {
deploy: (...args: A) => C;
}
// Some helper types
type FactoryArgs<F extends Factory<any, any>> = F extends Factory<infer A, any> ? A : never;
type FactoryContractType<F extends Factory<any, any>> = F extends Factory<any, infer C> ? C : never;
interface FactoryForClass<C extends new (...args: any) => Contract> {
//deploy: C extends new (...args: infer A) => infer T ? Factory<A, T>['deploy'] : never;
deploy: Factory<ConstructorParameters<C>, InstanceType<C>>['deploy'];
}
class CustomContract implements Contract {
constructor(a: number, b: number) { }
}
class CustomFactory implements FactoryForClass<typeof CustomContract> {
deploy(x: number, y: number): CustomContract {
return new CustomContract(x, y);
}
}
type MockContract<C extends Contract> = Contract & C & {
mockProperty: number;
}
type MockFactory<F extends Factory<any, any>> = F & {
deploy: (...args: FactoryArgs<F>) => MockContract<FactoryContractType<F>>;
}
const mockFactory: MockFactory<CustomFactory> = {
deploy(a: number, b: number) {
const customContract = new CustomContract(a, b);
const result: CustomContract & MockContract<CustomContract> = customContract as any;
result.mockProperty = 123;
return result;
}
};

最新更新