Choi Geonu
Choi Geonu

Reputation: 595

In Typescript, How can I merge object of generic container types into generic container of object type?

I'm trying to make a function that merges object of rxjs.Observables into single Observable.

For instance,

Suppose that I have a map of observables like following.

const fooObservable$: Observable<Foo> = createFooObservable();
const barObservable$: Observable<Bar> = createBarObservable();

// Type of observables would be
// { foo: Observable<Foo>, bar: Observable<Bar> }
// And, `keyof typeof observables` would be
// "foo" | "bar"
const observables = {
    foo: fooObservable$,
    bar: barObservable$,
};

then how can I make a function that merges observables like following?

// typeof merged$ would be
// Observable<{ foo: Foo, bar: Bar }>
const merged$ = merge(observables);

I can't figure out how to define the type signature of function merge()

Please give me an answer if there's a good way to do this.

Upvotes: 2

Views: 656

Answers (1)

dtanabe
dtanabe

Reputation: 1661

In this example, M is Observable (but it could really apply to any generic type):

class M<A> {
  value: A;
}

type Unpacked<T> = T extends M<infer U> ? U : never;

type MergeBody<T> = {
    [P in keyof T]: Unpacked<T[P]>
}

function merge<T>(t: T): M<MergeBody<T>> {
    ...
}

Then an example:

let o = {
    a: new M<number>(),
    b: new M<string>()
}

const m = merge(o)
// type checks!
let n: number = m.value.a

Upvotes: 3

Related Questions