Reputation: 136
I am trying to make function that returns Promise or Normal Value.
type Flow1 = <T, U>(a: T | Promise<T>, f: (a: T) => U) => U | Promise<U>
export const flow1: Flow1 = (a, f) => (a instanceof Promise ? a.then(f) : f(a))
flow1(Promise.resolve(4), (n) => n ** 2).then(console.log)
// Property 'then' does not exist on type 'number | Promise<number>'
But I get error when chaining then to the function. I have no idea what is wrong with this typing.
export function flow1<T, U>(a: T, f: (a: T) => U): U {
return f(a)
}
export function flow2<T, U>(a: Promise<T>, f: (a: T) => U): Promise<U> {
return a.then(f)
}
flow1(1, (n) => n ** 2)
flow2(Promise.resolve(1), (n) => n ** 2).then(console.log)
Okay is there any way to overload with same function name? :(
Upvotes: 2
Views: 885
Reputation: 371019
Although the flow1
function can, inside it, distinguish the difference between an a
argument that's a Promise and a plain value, TS doesn't allow the inference to propagate outside.
You'll have to examine the return value to see if you can call .then
on it:
type Flow1 = <T, U>(a: T | Promise<T>, f: (a: T) => U) => U | Promise<U>
export const flow1: Flow1 = (a, f) => (a instanceof Promise ? a.then(f) : f(a))
const result = flow1(Promise.resolve(4), (n) => n ** 2);
if (result instanceof Promise) {
result.then(console.log);
}
You could also use overloading, but it involves quite some boilerplate:
type Flow1 = {
<T, U>(a: T, f: (a: T) => U): void;
<T, U>(a: Promise<T>, f: (a: T) => U): Promise<U>;
};
const flow1: Flow1 = <T, U>(a: T | Promise<T>, f: (a: T) => U) => (a instanceof Promise ? a.then(f) : f(a));
flow1(Promise.resolve(4), (n: number) => n ** 2).then(console.log)
Upvotes: 2