【TypeError対策】async関数にthenが使えない?よくある落とし穴と解決法
`then is not a function` は、非同期処理の初学者が最もつまずくエラーの一つ。Promise や async/await の意味と役割から、型チェック・防止策までを図解&実例つきで解説!
async/await で「then is not a function」に遭遇した瞬間
非同期処理で .then()
を使っていたら、ある日こういうエラーに出くわしたことはありませんか?
TypeError: resolveError(...).then is not a function
一見「Promise っぽい関数を呼び出したつもり」なのに、.then()
が使えない…。このエラー、非同期処理の構造に潜む“思い込み”が原因です。
本記事では以下を順に解説し、理解 → 修正 → 再発防止の力をつけていきます。
- Promise・async・await とは何か?(用語理解)
- よくあるエラーのパターンと構造
- 安全な使い方と Lint・型・テストによる防御策
Promise とは? — 非同期処理の「未来の結果」
Promise(プロミス)とは、JavaScript の非同期処理を扱うためのオブジェクトです。
簡単に言えば「これから完了する処理の結果を表す箱」のようなもの。
const promise = new Promise((resolve, reject) => {
setTimeout(() => resolve('完了!'), 1000);
});
.then()
:成功時の処理.catch()
:失敗時の処理.finally()
:完了後に必ず実行
promise
.then((result) => console.log(result)) // => "完了!"
.catch((err) => console.error(err));
async/await とは?Promise をもっと読みやすくする仕組み
async とは?
async
をつけた関数は、常に Promise を返す関数になります。
async function greet() {
return 'Hello';
}
greet().then((msg) => console.log(msg)); // "Hello"
await とは?
await
は、Promise が「完了するまで待ってから」次の処理を実行するための構文です。
async function run() {
const msg = await greet();
console.log(msg); // "Hello"
}
async/await の利点
.then().then()
のネストを避けて、同期処理のようにスッキリ書けるtry/catch
でエラー処理が明確になる- 非同期処理を分かりやすく構造化できる
ケース 1:async なし → Promise じゃない戻り値に.then()して TypeError
ダメなコード例
function fetchData() {
return { data: 'hello' };
}
fetchData().then((res) => {
console.log(res.data); // TypeError
});
修正例
async function fetchData() {
return { data: 'hello' };
}
fetchData().then((res) => {
console.log(res.data);
});
// await の場合
async function main() {
const res = await fetchData();
console.log(res.data);
}
デバッグ Tips
const result = fetchData();
if (typeof result.then === 'function') {
result.then((res) => console.log(res));
} else {
console.warn('Promiseじゃないので.then()不可');
}
ケース 2:await 忘れ → undefined.then()の落とし穴
ダメなコード例
async function getUser() {
return { name: 'Alice' };
}
async function main() {
const user = getUser(); // await 忘れ
user.then((res) => {
console.log(res.name);
});
}
修正例
async function main() {
const user = await getUser();
console.log(user.name);
}
Lint での防止ルール
"rules": {
"require-await": "error",
"no-return-await": "error"
}
async/await と Promise の関係を図解で整理
[同期関数] → 値(ただのオブジェクト) → .then() ×
[async関数] → Promise<値> → .then() 〇
[await付きasync] → 値(Promiseの中身) → .then() ×(不要)
- async 関数は自動的に
Promise<戻り値>
を返す .then()
を使えるのは Promise に対してだけ- await を使うことで
.then()
を使わなくても中身が取り出せる
再発防止&設計ベストプラクティス
ESLint 設定例
"rules": {
"no-misused-promises": "error",
"consistent-return": "warn"
}
TypeScript の型チェック
async function getValue(): Promise<string> {
return 'hello';
}
const value: string = await getValue();
Jest テスト例
test('Promise resolves correctly', async () => {
const result = await getValue();
expect(result).toBe('hello');
});
まとめ & 関連リンク
- .then is not a function は「Promise を返していない」「await を忘れている」などが原因
- async/await/Promise の意味と役割を知ることが根本対策
- Lint・型チェック・テストで再発を未然に防ごう
【外部リンク】
【内部リンク】
JavaScriptでよく発生するエラー「ReferenceError」「SyntaxError」などの原因と対策を具体例付きで解説
TypeError: Cannot read property ‘xxx’ of undefined の原因と対処法を徹底解説【初心者向け】
なぜ「undefined」が出る?原因と解決法10選|JavaScript のデバッグに効く実例集