我创建了一个接受订阅者对象的函数,如下所示。
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>
。
返回对象的工作类型安全。
答案 0 :(得分:2)
因此,您希望ZipObservable
返回Observable<T>
类型的对象,其中输入参数与T
具有相同的键,但每个键K
的值都是EventEmitter<T[K]>
(其中T[K]
是类型K
的{{1}}键的属性值的类型。这绝对是可以实现的,通过mapped types和inference 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>>
导致结果;