我正在编写通用方法以便在不同的前端应用程序中使用它们,其想法是能够调用函数 .postAsync<CustomModel>('www.mysite.com',..., CustomModel); ,并且预期的响应是一个 CustomModel 对象。

我希望能够为第二个参数设置默认值,以便默认情况下该值将是不同的模型,并且可以在需要时覆盖。

如何为 Constructable<T> 类型的参数设置默认值,其中接口(interface) Constructable 意味着

interface Constructable<T> { new(params : any): T ;}

我试过设置一个接口(interface)的默认值,它接受一个参数并将参数设置为不同的类型,但我总是收到错误 Type Constructable<CustomModel> is not assignable to type Constructable<T> 。我还在通用方法中将 T 的默认类型设置为 CustomModel ,然后尝试此操作并得到相同的错误。
interface Constructable<T> { new(params : any): T ;}


export default class WebapiBase {

    static async postAsync<T = CustomModel>(
        uri: string,
        body: object,
        headers: CustomHeaders = new CustomHeaders(),
        // This is the part giving errors
        model: Constructable<T> = <Constructable<CustomModel>>,): Promise<T> {
        return this.requestAsync<T>(model, HTTP_METHOD.POST, uri, headers, body);
    }

    private static async requestAsync<T>(
        model: Constructable<T>,
        method: HTTP_METHOD,
        uri: string,
        headers: CustomHeaders,
        body?: object): Promise<T> {
        const url = new URL(uri, window.location.origin);
        const request = this.buildRequest(url, method, headers, body);
        const bodyResponse = await fetch(request)
            .then(response => this.validate(response, request.headers))
            .then(validResponse => this.extractBody(validResponse))
            // Here is where the response body is being used to initialise one of the custom models that we are passing in. Code below
            .then(extractedBody => this.buildModel<T>(model, extractedBody))
            .catch((error) => { throw this.handleError(error); });
        return bodyResponse;
    }

    private static buildModel<T>(
        Model: Constructable<T>,
        params: ResponseBody,
    ): T {
        return new Model(params);
    }
}


我希望我不必将模型传递给 postAsync() 方法,并且它总是会返回一个 CustomModel 对象。但实际上我收到了这个错误 Type Constructable<CustomModel> is not assignable to type Constructable<T>
Example in Playground, hover over Constructable in args to see error

最佳答案

我解决了这个问题,即在没有传递模型的情况下返回一个默认值(在这种情况下是一个通用对象)。
一般来说,修复是:

  • 将模型输入为 Constructable 接口(interface),而是使用 Constructable<T> | object 的联合类型。
  • 更改模型传入对象的默认值。
  • buildModel() 函数检查模型的类型,如果它是一个对象,则返回传入的值,如果它是可构造的,则创建它的一个实例。

  • 查看它是如何在 postAsync 参数、ResponseModel 接口(interface)和 buildModel 中实现的 requestAsync 方法中实现的:
    interface Constructable<T> { new(params : any): T ;}
    type ResponseModel<T> = Constructable<T> | Object;
    
    export default class WebapiBase {
      static async postAsync<T = Object>(
          {
              uri = '',
              body = {},
              headers = new CustomHeaders(),
          }: PostRequestParams = {},
          // Here is where the defualt is implemented
          model: ResponseModel<T> = Object): Promise<T> {
          return this.requestAsync(model, HTTP_METHOD.POST, uri, headers, body);
      }
      private static async requestAsync<T = Object>(
          // This param accepts either a class or object
          model: ResponseModel<T>,
          method: HTTP_METHOD,
          uri: string,
          headers: CustomHeaders,
          body?: object): Promise<T> {
          const url = new URL(uri, window.location.origin);
          const request = this.buildRequest(url, method, headers, body);
          const bodyResponse = await fetch(request)
              .then(response => this.validate(response, request.headers))
              .then(validResponse => this.extractBody(validResponse))
              // Class instance or object returned here
              .then(extractedBody => this.buildModel(model, extractedBody))
              .catch((error) => { throw this.handleError(error); });
          return bodyResponse;
      }
    
      // Method that conditionally creates an instance of the passed in model
      // Or returns the object passed in if no model specified
      private static buildModel<T = Object>(
            Model: ResponseModel<T>,
            params: any,
        ): T {
            if (typeof Model === 'object') return params;
            return new Model(params);
      }
    }
    

    关于typescript - 当参数的类型是泛型时,是否可以在 typescript 中为参数设置默认值?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56364384/

    10-11 07:40