This error occurs when you annotate an async function with a non-Promise return type. Async functions always return a Promise, so TypeScript requires you to wrap the return type in Promise<T>.
In TypeScript, when you declare a function with the `async` keyword, the function is guaranteed to return a Promise, even if you don't explicitly return one. The `await` keyword inside async functions only works with Promises. When you specify a return type annotation for an async function, TypeScript requires that type to be `Promise<T>` where `T` is the type of the value being resolved. If you try to annotate an async function with a non-Promise type (like `string`, `number`, or a custom object), TypeScript will raise error TS1058. This is a fundamental requirement in TypeScript's type system—it ensures type safety when working with asynchronous code.
Look for the function causing the error. It will look something like this:
async function getUsername(): string { // ❌ Error: TS1058
const user = await fetchUser();
return user.name;
}The issue is that the return type is annotated as string, but async functions must return Promise<string>.
Change the return type annotation to Promise<T> where T is your original type:
// ✅ Correct - Named function
async function getUsername(): Promise<string> {
const user = await fetchUser();
return user.name;
}
// ✅ Correct - Arrow function
const getUsername = async (): Promise<string> => {
const user = await fetchUser();
return user.name;
};
// ✅ Correct - Class method
class UserService {
async getUsername(): Promise<string> {
const user = await fetchUser();
return user.name;
}
}The function body doesn't change—only the type annotation.
If your async function doesn't return a value, use Promise<void>:
// ❌ Error
async function logUser(): undefined {
const user = await fetchUser();
console.log(user.name);
}
// ✅ Correct
async function logUser(): Promise<void> {
const user = await fetchUser();
console.log(user.name);
}If your async function can return different types, use a union type inside Promise:
// ✅ Return a union
async function fetchData(): Promise<string | null> {
try {
return await api.getData();
} catch {
return null;
}
}
// ✅ Return an object
async function getUser(): Promise<{ id: string; name: string }> {
const response = await fetch('/api/user');
return response.json();
}
// ✅ Return an array
async function getUsers(): Promise<User[]> {
const response = await fetch('/api/users');
return response.json();
}Run TypeScript compiler to check for errors:
npx tsc --noEmitOr if using a development server:
npm run devThe error should now disappear. If you're using an IDE, save the file and let the language server re-check it.
### Type Inference
TypeScript can often infer the Promise return type automatically if you don't annotate it:
// TypeScript infers: Promise<string>
async function getName() {
return 'John';
}However, explicit annotations are recommended for clarity and to catch type errors early.
### Thenable Objects
An async function's return type must be a true Promise or the global Promise type. Custom thenable objects (with a .then method) may not work as expected:
// ❌ May cause issues
async function getPromiseLike(): MyCustomThenable {
return new MyCustomThenable();
}
// ✅ Wrap in Promise
async function getPromiseLike(): Promise<MyType> {
return new Promise((resolve) => {
resolve(new MyCustomThenable());
});
}### Async Generators
If using async generators (returning an AsyncIterable), the syntax is different:
// ✅ Async generator function
async function* generateData(): AsyncGenerator<string, void, unknown> {
yield 'data1';
yield 'data2';
}### TypeScript 4.1+ --noImplicitAny
If you have --noImplicitAny enabled and don't annotate the return type, TypeScript will infer it. Without the flag, you may need explicit annotations to avoid TS7010 (Parameter implicitly has 'any' type).
Function expression requires a return type
Function expression requires a return type
Value of type 'string | undefined' is not iterable
How to fix "Value is not iterable" in TypeScript
Type 'undefined' is not assignable to type 'string'
How to fix "Type undefined is not assignable to type string" in TypeScript
Type narrowing from typeof check produces 'never'
How to fix "Type narrowing produces never" in TypeScript
Type parameter 'T' has conflicting constraints
How to fix "Type parameter has conflicting constraints" in TypeScript