简体   繁体   English

传递通用类类型作为通用函数的参数

[英]Pass a generic class type as a parameter of a generic function

I'm using a converter (external library) that has a method fromJson like the one below. 我正在使用具有来自Json的方法的转换器(外部库),如下所示。 I want to build a generic RESTService, but i don't know how to pass the generic class type to the method. 我想构建一个通用的RESTService,但是我不知道如何将通用的类类型传递给该方法。

// From the library
export declare type Clazz<T> = {
  new (...args: any[]): T;
};

// From the library
export class Converter {
  ...
  public fromJson<T>(json: any, clazz: Clazz<T>): T { ... }
  ...
}

// ******************************************************

// My Service on my Angular app
class RESTService<T> {
  ...
  public save(t: T): Observable<T> {
    return this.httpClient.post('http://...', t)
      .pipe(map(res => this.converter.fromJson(res, ???)));
  }
  ...
}

You can use t.constructor as the Clazz<T> argument. 您可以将t.constructor用作t.constructor Clazz<T>参数。 You'll need to tell TypeScript it is of the right type using as : 您需要使用as告诉TypeScript正确的类型:

// From the library
declare type Clazz <T> = {
    new(...args: any[]): T;
};

// From the library
class Converter {
    public fromJson<T>(json: any, clazz: Clazz<T>) { return new clazz(); }
}

class Test {
    public testIt<T>(test: T) {
        const converter = new Converter();
        var o = converter.fromJson("{}", test.constructor as new (...args: any[]) => T);
        return o;
    }
}

class TestObj {
    testProp: string = "hello";
}

var o = new TestObj();
var t = new Test();
var a = t.testIt(o);
console.log(JSON.stringify(a));

This seems to compile and work in the TypeScript Playground , but as always, you should test it out in your own environment. 这似乎可以在TypeScript Playground中进行编译和工作 ,但是与往常一样,您应该在自己的环境中对其进行测试。

I did alter fromJson just so that I could get a loggable result, and obviously testIt is not exactly the same as your (Angular?) function, but hopefully it gets you going in the right direction. 我做了一些改变,只是为了让fromJson可以得到可记录的结果,并且显然testIt与您的(Angular?)函数并不完全相同,但是希望它可以使您朝正确的方向前进。

  1. The library you are using is very bad and has semantic errors. 您使用的库非常糟糕,并且存在语义错误。 new is a keyword used to initialize an instance of a class type. new是用于初始化类类型的实例的关键字。 The return type is should always be consistent with this class type. 返回类型应始终与此类类型一致。 The correct definition should be: 正确的定义应为:

     export declare type Clazz<T> = { new (...args: any[]): Clazz<T>; }; 
  2. Solve this problem. 解决这个问题。 You can always use the keyword as and Object.create(null) to convert most object types to avoid compiler checking: 您始终可以使用关键字asObject.create(null)来转换大多数对象类型,以避免编译器检查:

     class RESTService<T> { ... public save(t: T): Observable<T> { let clazz = Object.create(null) as Clazz<T>; // clazz.someValue = 'Hello world'; return this.httpClient.post('http://...', t) .pipe(map(res => this.converter.fromJson(res, clazz))); } ... } 

    Object.create(null) give you a js object without any method binding --- a pure struct space. Object.create(null)为您提供一个没有任何方法绑定的js对象-纯结构空间。

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

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