20160821

ES6 Promise Types and Errors

I've been working on a new project using NodeJS. Again, I'm using TypeScript for added safety, which means I have to (and want to) play nice with the type system. This code also uses ECMAScript 6 Promises for asynchronous database queries, and I ran into some funny (like funny uh-oh) problems here. But also solutions, so I thought I'd share.

Promises are templated with the type of value they return in success, i.e. what's passed to resolve, but if you reject a promise, can the Typescript compiler figure out what template type it is? Let's say I have code that looks like this, where I'm wrapping the error from the database library with my own error type.

query.execute().then(function(result : RecordSet) : Promise<MyResults>
{
    // compiler can deduce it's a Promise<MyResults> by the parameter to
    // resolve()
    return Promise.resolve(new MyResults(result));
}, function(err : any) : Promise<MyResults>
{
    // Promise is only templated on the success type, so can it figure out the
    // template type from a reject call?
    return Promise.reject(new MyError(ERROR_TYPE_GENERIC, err));
});

This produces a Typescript error: TS2322: Type 'Promise<void>' is not assignable to type 'Promise<MyResults>'. So Promise.reject implicitly returns a Promise<void> object. Can I return one with a different type? Here's an attempt:

return Promise<MyResults>.reject(new MyError(ERROR_TYPE_GENERIC, err));

error TS1005: '(' expected.
error TS1005: ')' expected.

That's a syntax error. Guess that wasn't it. After much fumbling, I figured it out, so I wanted to share here:

return Promise.reject<MyResults>(new MyError(ERROR_TYPE_GENERIC, err));

OK, thanks, totally arbitrary syntax. I also think it's interesting that the Promise object isn't templated with both the type of the value and the type of the error, for extra safety.

0 comments:

Post a Comment