【问题标题】:Pass a generic class type as a parameter of a generic function将泛型类类型作为泛型函数的参数传递
【发布时间】:2019-03-05 08:05:52
【问题描述】:

我正在使用具有 fromJson 方法的转换器(外部库),如下所示。 我想构建一个泛型 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, ???)));
  }
  ...
}

【问题讨论】:

  • 您将对象传递给fromJson 是否有原因?似乎您只想说fromJson 返回一个Clazz&lt;T&gt; 类型的对象...所以fromJson(json: any): Class&lt;T&gt; {}
  • fromJson 是一个外部库的方法,我改不了。
  • @TitianCernicova-Dragomir 我已经更新了问题。
  • 看起来它要求一个构造函数或类类型。
  • 是的,但是如何传递我的通用休息服务的另一个通用类类型 T?

标签: angular typescript generics


【解决方案1】:

您可以使用t.constructor 作为Clazz&lt;T&gt; 参数。您需要使用 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,但一如既往,您应该在自己的环境中对其进行测试。

我确实更改了fromJson,以便获得可记录的结果,显然testIt 与您的(Angular?)函数并不完全相同,但希望它能让您朝着正确的方向前进。

【讨论】:

    【解决方案2】:
    1. 您使用的库非常糟糕并且存在语义错误。 new 是用于初始化类类型实例的关键字。返回类型应始终与此类类型一致。正确的定义应该是:

      export declare type Clazz<T> = {
        new (...args: any[]): Clazz<T>;
      };
      
    2. 解决这个问题。您始终可以使用关键字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) 给你一个没有任何方法绑定的 js 对象——一个纯结构空间。

    【讨论】:

      猜你喜欢
      • 2019-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多