简体   繁体   English

打字稿:包装函数返回泛型类的类型

[英]Typescript: Wrap function return type of generic class

I am not being able to wrap my head around this issue in a generic way with Typescript, I would appreciate any help!我无法使用 Typescript 以通用方式解决这个问题,我将不胜感激!

  • A Factory should deploy a Contract工厂应该部署合同
  • A CustomFactory is a Factory and should deploy a CustomContract (that is a Contract) CustomFactory 是一个工厂,应该部署一个 CustomContract(即一个 Contract)
  • A MockFactory should be a wrapper of all this logic MockFactory 应该是所有这些逻辑的包装器

Something like this would be the goal (semi pseudocode)像这样的东西将是目标(半伪代码)

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

In order to illustrate the issue even better I created a Playground where you can see the errors为了更好地说明问题,我创建了一个Playground ,您可以在其中看到错误

Just solved by using ReturnType and Parameters, as well needed to transform the interface into a type:刚刚通过使用 ReturnType 和 Parameters 解决了,以及将接口转换为类型所需的:

Updated Playground 更新的游乐场

You could go with (abstract) classes, but interfaces are possible too.您可以使用(抽象)类,但接口也是可能的。 In that case, making the factory itself generic seems like the wrong move.在这种情况下,使工厂本身通用似乎是错误的举动。 Make the contract type generic instead.改为使合同类型通用。 After a bit of playing around, I was able to puzzle this together:经过一番玩耍后,我能够将其拼凑在一起:

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;
    }
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM