This rule raises an issue when an async function does not use any asynchronous feature.

Why is this an issue?

Declaring a function async signals that it suspends on await or for await, so other work can proceed while an operation such as I/O completes.

If the function’s body never suspends, the async keyword is superfluous. Using async unnecessarily can:

Remove the async keyword. If the function’s return type must remain a Promise, for example to satisfy an interface or base class, wrap the return value with Promise.resolve() instead of marking the function async.

Code examples

Noncompliant code example

async function greet(name) { // Noncompliant: never uses "await"
  console.log(`Hello, ${name}`);
}

Compliant solution

function greet(name) { // Compliant
  console.log(`Hello, ${name}`);
}

Noncompliant code example

async function getUserName(user) { // Noncompliant: nothing is awaited, "async" only wraps the result in a Promise
  return user.name;
}

Compliant solution

function getUserName(user) {
  return user.name;
}

Noncompliant code example

interface Repository {
  save(entity: Entity): Promise<void>;
}

class InMemoryRepository implements Repository {
  async save(entity: Entity): Promise<void> { // Noncompliant: "async" only wraps the return value in a Promise
    this.entities.push(entity);
  }
}

Compliant solution

interface Repository {
  save(entity: Entity): Promise<void>;
}

class InMemoryRepository implements Repository {
  save(entity: Entity): Promise<void> { // Compliant: satisfies the contract without "async"
    this.entities.push(entity);
    return Promise.resolve();
  }
}

Exceptions

This rule does not raise an issue in the following cases:

async function stub() {} // Compliant: empty body

async function relay(id) {
  return fetchUser(id); // Compliant: the return value is already a Promise
}

async function* stream(source) {
  yield* source; // Compliant: delegates to an async-iterable source
}

Requiring a Promise return type through an interface, decorator, or base class does not exempt a method from this rule. Using async only to coerce a non-promise return value into a Promise, with no actual suspension in the body, is exactly the pattern this rule targets. See the Repository example above for the recommended fix.

Resources

Documentation