Reputation: 4770
My await statements inside the async functions are calls to jQuery's $.post() method which return a valid promise, however I am getting this error in TypeScript:
Type of 'await' operand must either be a valid promise or must not contain a callable 'then' member.
My function is this (simplified for the example). The code is valid and works, but I am getting a error in the TS console.
async function doAsyncPost() {
const postUrl = 'some/url/';
const postData = {name: 'foo', value: 'bar'};
let postResult;
let upateResult;
function failed(message: string, body?: string) {
console.log('error: ', message, ' body: ', body);
}
function promiseFunc() {
return new Promise<void>( resolve => {
// ... do something else....
resolve();
});
};
function finish() {
// ... do something at the end...
}
try {
// The error is on the $.post()
postResult = await $.post(postUrl, $.param(postData));
if (postResult.success !== 'true') {
return failed('Error as occoured', 'Description.....');
}
await promiseFunc();
return finish();
} catch (e) {
await failed('Error as occoured', 'Description.....');
}
}
I'm guessing TS is having a problem with $.post() because you can call .then() on it, but how do I get around this problem? Also, I did not have this error prior to updating 2.4.2.
Upvotes: 24
Views: 32602
Reputation: 350881
Seems indeed TypeScript is pesky about jQuery returning a promise object which is both a deferred and a jqXHR object:
The jqXHR objects returned by
$.ajax()
as of jQuery 1.5 implement the Promise interface, giving them all the properties, methods, and behavior of a Promise (see Deferred object for more information).
There are at least three workarounds to this stubbornness of TypeScript
You could pass the return value to Promise.resolve()
, which will return a true ES6 Promise, promising the same value:
postResult = await Promise.resolve($.post(postUrl, $.param(postData)));
The other two alternatives do not return pure ES6 promises, but jQuery promises, which still is good enough. Be aware though that these promise objects are only Promises/A+ compliant from jQuery 3 onwards:
You could apply the deferred.promise
method, which returns a jQuery promise object:
postResult = await $.post(postUrl, $.param(postData)).promise();
Alternatively, you could apply the deferred.then
method, which also returns a jQuery promise:
As of jQuery 1.8, the
deferred.then()
method returns a new promise
By not providing any argument to then
you effectively return a promise for the same promised value:
postResult = await $.post(postUrl, $.param(postData)).then();
Upvotes: 33
Reputation: 2686
JQueryXHR has its own version of .then() which has some additional options:
then<R>(doneCallback: (data: any, textStatus: string, jqXHR: JQueryXHR) => R, failCallback?: (jqXHR: JQueryXHR, textStatus: string, errorThrown: any) => void): JQueryPromise<R>;
To use await in TypeScript with $.post, I had to remove that line from jquery.d.ts. TypeScript will then see the .then defined on JQueryGenericPromise.
Upvotes: 1