I have a regular promise with a statically typed return type:
export const hasActiveSubscription = (whatEver: string): Promise<string> =>
new Promise((resolve, reject) => {
if (true){
return resolve('imastring')
}
return reject(new Error('nope'))
})
So far so good, but if I add a finally block, it changes the return type to unknown
and fails to deliver that string type, e.g.
export const hasActiveSubscription = (whatEver: string): Promise<string> =>
new Promise((resolve, reject) => {
if (true){
resolve('imastring')
}
reject(new Error('nope'))
}).finally(console.info)
Type 'Promise' is not assignable to type 'Promise'.
Type 'unknown' is not assignable to type 'string'.
How can I retain the original return type while keeping the finally
block?
If it helps, my actual code has a setTimeout
(to be sure this function doesn't take too long to return) and I want to clear the timeout on finally, instead of clearing a timeout on 5 different locations.
If you remove type annotation from the return position of the function signature, you will notice that the actual return type is Promise<unknown>
, not the Promise<string>
as you expected, which constitutes the first part of the error:
const hasActiveSubscription: (whatEver: string) => Promise<unknown>;
Promise
is a generic interface, and its finally
method uses the type parameter of the interface in its return type annotation (the sample is from the ES2018 lib):
interface Promise<T> {
finally(onfinally?: (() => void) | undefined | null): Promise<T>
}
All you need to do is to specify the type of the constructed Promise, and everything will be a-ok:
export const hasActiveSubscription = (whatEver: string) =>
new Promise<string>((resolve, reject) => {
if (true){
resolve('imastring')
}
reject(new Error('nope'))
}).finally(console.info) //no error, Promise<string> is inferred
Small note - your example has an unmatched bracket in the reject
call