简体   繁体   English

如何 map 将 object 文字中的多个主题转换为相应 Observable 的 object 文字

[英]How to map multiple Subject in an object literal to an object literal of corresponding Observable

I am working on a class in Angular and want to share a bunch of states belong to that class.我正在研究 Angular 中的 class 并想分享属于该 class 的一堆状态。 So I make a bunch of BehaviorSubject所以我做了一堆BehaviorSubject

private subjects = {
    a : new BehaviorSubject<A>(this.a),
    b : new BehaviorSubject<B>(this.b),
    c : new BehaviorSubject<C>(this.c),
    d : new BehaviorSubject<D>(this.d),
    e : new BehaviorSubject<E>(this.e),
}

To prevent leaking the Observer side of the subjects and only expose the Observable side, I make the subjects private and expose with observables:为了防止泄露主体的Observer端并且只暴露Observable端,我将主体设为私有并使用 observables 公开:

observables = {
    a : this.subjects.a.pipe(share()),
    b : this.subjects.b.pipe(share()),
    c : this.subjects.c.pipe(share()),
    d : this.subjects.d.pipe(share()),
    e : this.subjects.e.pipe(share()),
}

I think the observables should be able to be generated from the subjects so that when I want to add more subjects, I don't need to modify the observables manually.我认为 observables 应该能够从主题中生成,这样当我想添加更多主题时,我不需要手动修改 observables。 Something like:就像是:

observables = (()=>{
    let observables : {[Property in keyof typeof this.subjects]:Observable} = {}
    for(let key in this.subjects)
    {
        observables[key] = this.subjects[key as keyof typeof this.subjects].pipe(share())
    }
    return observables;
})();

But here Observable and share do not know their generic type.但是这里的Observableshare不知道它们的泛型类型。 How can I make this work or if there is better pattern?我怎样才能使这项工作或是否有更好的模式?

As far as I am aware you don't need to share the BehaviorSubject observable as it is already hot via the BehaviorSubject .据我所知,您不需要share BehaviorSubject可观察对象,因为它已经通过BehaviorSubject很热。

You can solve the generic typing issues by using Mapped types :您可以使用Mapped types解决通用类型问题:

const subjects = {
  a: new BehaviorSubject<number>(1),
  b: new BehaviorSubject<string>('foo'),
  c: new BehaviorSubject<boolean>(false),
};

// utility type to convert BehaviorSubject<T> to Observable<T> 
// (can be inlined below instead)
type BehaviorSubjectToObservable<T> = 
  T extends BehaviorSubject<infer U> ? Observable<U> : never;

// create appropriate type for resulting object which has the same keys
// but maps to Observable<T>
// this ensures correct typing within the reduce
type Observables<T> = {
  [P in keyof T]: BehaviorSubjectToObservable<T[P]>;
};

// transform the object
const observables = Object.entries(subjects).reduce(
  (acc, [key, subject]) => ({ ...acc, ...{ [key]: subject.asObservable() } }),
  {} as Observables<typeof subjects>,
);

// typeof observables.a = Observable<number>
// typeof observables.b = Observable<string>
// typeof observables.c = Observable<boolean>

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

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