Stefdelec
Stefdelec

Reputation: 2811

How to transform an object of Promise to object of Observable and still have typescript typings?

I am having an object of Promise. I like to transform all of them into observable (rxjs) but I want to keep the typing. This way is not working:

const methods = {
    func1: (): Promise<boolean> => {
        return Promise.resolve(true)
    },
    func2: (num: number): Promise<number> => {
        return Promise.resolve(num)
    }
};

const mapItToObservable = (methods) => {
    return Object.keys(methods).reduce((acc, key) => {
        acc[key] = from(acc[key])
        return acc;
    }, {})
}

const methodsInObservable = mapItToObservable(methods)

methodsInObservable.func1.subscribe(d => console.log('d'))

Any idea?

Upvotes: 0

Views: 35

Answers (1)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249476

So if my reading of this question is correct, you want to map an object containing functions returning promises to functions returning observable.

You can make the types work out using a mapped type to map the properties of the original type and a conditional type to extract the parameters and the result type and then use it to create the new function signature:


type MapToObservable<T extends Record<string, (...args: any[]) => Promise<any>>> = {
    [P in keyof T]: T[P] extends (...args: infer P) => Promise<infer R> ? (...args: P) => Observable<R> : never
}

The function itself needs to correctly call the promise function and return the observable:


const methods = {
    func1: (): Promise<boolean> => {
        return Promise.resolve(true)
    },
    func2: (num: number): Promise<number> => {
        return Promise.resolve(num)
    }
};

type MapToObservable<T extends Record<string, (...args: any[]) => Promise<any>>> = {
    [P in keyof T]: T[P] extends (...args: infer P) => Promise<infer R> ? (...args: P) => Observable<R> : never
}

const mapItToObservable = <T extends Record<string, (...args: any[]) => Promise<any>>>(methods: T) => {
    return Object.keys(methods).reduce((acc, key) => {
        acc[key] = function (...args: any[]) {
            return from(methods[key].call(this, ...args))
        }
        return acc;
    }, {} as Record<string, (...args: any[]) => Observable<any>>) as any as MapToObservable<T> ;
}

const methodsInObservable = mapItToObservable(methods)

methodsInObservable.func1().subscribe(d => console.log('d'))

Play

Upvotes: 2

Related Questions