是否可以从泛型中获取类型,作为参数给出

时间:2017-10-20 11:54:20

标签: angular typescript events observable type-safety

我创建了一个接受订阅者对象的函数,如下所示。

public subscribers = {
    count: <EventEmitter<number>>new EventEmitter<number>(),
    staticCount: <EventEmitter<number>>new EventEmitter<number>()
};

此函数等待两个observable完成,并返回一个对象及其收到的对象的键,作为EventEmitter发出的值的值。

type AnyType<T> = {
    [P in keyof T]: any;
}

function ZipObservable<T extends { [name: string]: EventEmitter<any>}>
    (observables: T): Observable<AnyType<T>> {
    const m = CreateMapFromObject(observables);
    const o = new Subject<any>();

    Observable.zip(...Array.from(m.values())).subscribe((res) => {
        const keys = m.keys();
        const c = res.reduce((r, v) => {
            const k = <string>keys.next().value;
            r[k] = v;

            return r
        }, {});

        /**
         *
         */
        o.next(c);
        o.complete();
    });

    return o.asObservable();
}

我当前的问题是返回对象中设置的值的类型。键入其键的对象(如图中所示)。

我还希望将值的类型设置为number(在本例中)。 我创建了一个类型; AnyType<T>能够将返回的对象设置为其键。是否有可能让它设置其值的类型?

我希望它成为的类型,来自参数,它接收一个泛型; EventEmitter<number>

返回对象的工作类型安全。

screenshot

2 个答案:

答案 0 :(得分:2)

因此,您希望ZipObservable返回Observable<T>类型的对象,其中输入参数与T具有相同的键,但每个键K的值都是EventEmitter<T[K]>(其中T[K]是类型K的{​​{1}}键的属性值的类型。这绝对是可以实现的,通过mapped typesinference from mapped types

首先让我们定义一个映射类型,它接受T中的每个属性并将其转换为适当类型的T

EventEmitter<>

现在type EventEmitters<T> = { [K in keyof T]: EventEmitter<T[K]> } 函数签名可以直接编写(我将把实现留给你):

ZipObservable

它的工作原理是因为来自映射类型的推断:

declare function ZipObservable<T>(eventEmitters: EventEmitters<T>): Observable<T>; 

希望有所帮助;祝你好运!!

答案 1 :(得分:0)

非常感谢@jcalz

你让我走上了正确的道路。你的代码工作了。它删除了我的类型安全,所以我稍微调整了一下。

- 编辑

它没有消除我的类型安全性。我的编辑器只是无法识别返回对象上的键。当我使用下面的代码时它会这样做。

type EmittedReturnType<T> = {
    [K in keyof T]: T[K]
}

type EventEmitters<T> = {
    [K in keyof T]: EventEmitter<T[K]>
}

所以,

我创造了两种类型;第一种类型是参数类型。第二种类型是返回类型。

declare function ZipObservable<T>(observables: EventEmitters<T>): Observable<EmittedReturnType<T>>

导致结果;

A type safe object.

A type safe assign