【问题标题】:How to create a new object of type 'T' in generic class in typescript?如何在打字稿的泛型类中创建类型为“T”的新对象?
【发布时间】:2017-12-14 02:52:06
【问题描述】:

我有以下服务

@Injectable()
export class CollectionService<T> {    

    constructor(protected http: Http) {}

    factory<T>(item?: any): T {
        let type: new (item?: any) => T;
        return new type(item);
    }

    item(id): Observable<T> {
        return this.http.get(`${this.baseUrl}/${id}`)
            .map((resp: Response)=> this.factory(resp.json()))
            .catch((error: any) => {
                return Observable.throw(error);
            });
    }
}

编译成功,但浏览器控制台出现以下错误

TypeError: type is not a constructor
at PortalVideoService.webpackJsonp.../../../../../src/app/services/collection/collection.service.ts.CollectionService.factory (http://localhost:4200/main.bundle.js:1568:16)
at http://localhost:4200/main.bundle.js:1580:64
at Array.map (native)
at MapSubscriber.project (http://localhost:4200/main.bundle.js:1580:29)
at MapSubscriber.webpackJsonp.../../../../rxjs/operator/map.js.MapSubscriber._next (http://localhost:4200/vendor.bundle.js:24034:35)
at MapSubscriber.webpackJsonp.../../../../rxjs/Subscriber.js.Subscriber.next (http://localhost:4200/vendor.bundle.js:13455:18)
at XMLHttpRequest.onLoad (http://localhost:4200/vendor.bundle.js:101703:38)
at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask (http://localhost:4200/polyfills.bundle.js:2838:31)
at Object.onInvokeTask (http://localhost:4200/vendor.bundle.js:93420:37)
at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask (http://localhost:4200/polyfills.bundle.js:2837:36)

如何创建 T 类型的对象?

【问题讨论】:

    标签: angular typescript angular2-services typescript-generics


    【解决方案1】:

    您可以将构造函数作为类泛型而不是方法传递。

    export class CollectionService<T, CT extends { new(item?: any): T }> {    
    
        constructor(protected http: Http, private type: CT) {}
    
        factory(item?: any): T {
            return new this.type(item);
        }
    
        // ...
    }
    
    class CustomClass {
        constructor(private item?: any) {
        }
     };
    
    
    let cs = new CollectionService<CustomClass, { new(): CustomClass }>(http, CustomClass);
    console.dir(cs.factory(123));
    
    // UPDATE
    class CustomClassService extends CollectionService<CustomClass, { new(): CustomClass }> {
        constructor(protected http: Http) {
            super(http, CustomClass);
        }
    }
    
    let ccs = new CustomClassService(http);
    console.dir(ccs.factory(456));
    

    【讨论】:

    • ERROR in Error encountered resolving symbol values statically. Could not resolve type CT (position 14:52 in the original .ts file), resolving symbol CollectionServiceng build -prod
    • 但是没有泛型类型参数。不是吗?
    • 我想是的...也许是CustomClassService?我更新了答案。
    【解决方案2】:

    名称T 仅在编译时存在。您可以将其用于类型检查,但您不能构造 T 类型的对象,除非您有权访问构造函数。

    更改factory的定义,将运行时类型构造函数作为参数:

    factory<T>(type: {new(): T}, item?: any): T {
        return new type(item);
    }
    

    现在唯一的问题是弄清楚你从哪里得到类型参数;您可能还需要将它传递给item() 方法,以便编译器知道要生成Observable&lt;T&gt; 的类型。

    【讨论】:

    • 我试图通过类构造函数传递一个类型。 constructor(protected http: Http, private type: {new(item: any): T})。它很丑,但效果很好。但是当我做ng build -prod 我得到ERROR in Error encountered resolving symbol values statically. Expression form not supported (position 14:53 in the original .ts file)
    • 谷歌搜索该错误似乎表明它是您的角度模板中的问题。 medium.com/@isaacplmann/…(第 4 节)
    【解决方案3】:

    不需要做你正在做的事情,只需做

    .map((resp: Response)=> resp.json())
    

    如果您想要响应的自定义类型,请执行

    .map((resp: Response)=> resp.json() as CustomResponse) 
    

    CustomResponse 是一个接口。

    【讨论】:

    • 在这种情况下,我仍然得到一个简单的 Object 而不是 T 类型的对象。.map((resp: Response)=&gt; resp.json() as T)
    • 如果CustomResponse 是一个接口就可以,但是如果它是一个有自己的方法的类就不行。为此,您必须像 OP 一样尝试并从响应中实际创建一个真实对象。
    • @Duncan True,尽管我仍然觉得很难看到这样做的用例?
    • @Duncan 我怎样才能创建一个真实的对象?
    • @AndreyK 查看我发布的答案,您必须将实际类型作为参数传递
    猜你喜欢
    • 2018-04-27
    • 2020-10-11
    • 2019-01-16
    • 2020-05-25
    • 2017-09-15
    • 2022-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多