@async is a JSDoc documentation tag for a function that runs asynchronously. TypeScript 5.9 ignores it: a function tagged @async that returns a string still has the return type string, and calling .then() on its result is an error.
TypeScript gets the same information from the code itself. An async function always returns a promise, and @returns {Promise<T>} says what the promise resolves to. The handbook names @async as an example of a tag TypeScript does not support.
At a glance
| Use | JSDoc in a .js file | TypeScript in a .ts file |
|---|---|---|
| An async function | /** @returns {Promise<string>} */
async function load() { … } | async function load(): Promise<string> { … } |
Examples
/**
* @async
* @returns {Promise<string>}
*/
export function loadGreeting() {
return "hello";error TS2322: Type 'string' is not assignable to type 'Promise<string>'.
}jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} /**
* @param {string} url
* @returns {Promise<string>}
*/
export async function loadText(url) {
const response = await fetch(url);
return response.text();
}
loadText("/greeting.txt").then((text) => text.trim());export async function loadText(url: string): Promise<string> {
const response = await fetch(url);
return response.text();
}
loadText("/greeting.txt").then((text) => text.trim());jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} How we tested it
The failing example tags a plain function @async, declares @returns {Promise<string>} and returns a string. If TypeScript read @async, the string would be wrapped in a promise and the return would be fine. tsc reports TS2322 instead ("Type 'string' is not assignable to type 'Promise<string>'"), so the tag is not read.
Typing async functions
Write the async keyword and describe the resolved value with @returns {Promise<T>}. Without the tag, TypeScript infers the promise type from the return statements, which is often enough for small functions.
The return type of an async function must be a Promise type. @returns {boolean} on an async function is an error (TS1064), and the message suggests the Promise<boolean> you meant.
Gotchas
- Returning a promise from a non-async function is fine:
function load() { return fetch(url); }is typed as returningPromise<Response>with or without any tag. - Inside an
asyncfunction,return valueandreturn Promise.resolve(value)produce the same type; TypeScript unwraps nested promises withAwaited.
Questions
Do I need @async if I use the async keyword?
No. TypeScript reads the keyword. Keep @async only if a documentation tool you run needs it; it does no harm, but it does nothing for checking.
Sources
- @async · JSDoc
- JSDoc Reference · TypeScript handbook
- Everyday Types: functions that return promises · TypeScript handbook
Last reviewed 20 October 2026.