TypeScript访问Firebase返回数据提示类型为never的问题如何解决?
问题原因
TypeScript 的控制流分析存在局限性,无法追踪高阶函数回调中对外部变量的赋值操作:
你使用的 forEach 是高阶函数,回调内对 playerOneData、playerTwoData 的赋值属于回调副作用,TS 不会主动分析这类副作用的执行逻辑。因此 TS 会认为这两个变量从初始化后就一直保持 null 值,你写的非空判断 if (playerOneData == null || playerTwoData == null) 会被判定为永远为真,代码永远走不到后续的 console.log 分支,该分支下的两个变量类型就被推断为不可能存在的 never 类型。
解决方案
方案1:替换 forEach 为普通 for...of 循环(推荐)
普通迭代逻辑在 TS 的控制流分析范围内,可以正确识别变量的赋值操作:
async function test() { let playerOneData: FirebaseFirestore.DocumentData | null = null; let playerTwoData: FirebaseFirestore.DocumentData | null = null; const players = await db .collection("Games/ANY_ID/Players") .where(admin.firestore.FieldPath.documentId(), "in", ["PLAYER1_ID", "PLAYER2_ID"]) .get(); // 替换为for...of遍历 for (const doc of players.docs) { if (doc.id == "PLAYER1_ID") { playerOneData = doc.data(); } if (doc.id == "PLAYER2_ID") { playerTwoData = doc.data(); } } if (playerOneData == null || playerTwoData == null) { return null; } // 类型已经可以被正确推断为DocumentData console.log(playerOneData.test + " " + playerTwoData.test); }
方案2:添加类型断言(临时适配)
如果你不想修改循环逻辑,可以在访问属性时手动指定类型:
console.log((playerOneData as FirebaseFirestore.DocumentData).test + " " + (playerTwoData as FirebaseFirestore.DocumentData).test);
额外优化:自定义类型提升安全度
FirebaseFirestore.DocumentData 是泛用的无约束对象类型,后续访问属性时仍可能出现类型提示缺失的问题。你可以自定义玩家数据类型,在调用 data() 时指定类型:
interface Player { test: string; // 其他玩家字段 } // 赋值时指定类型 playerOneData = doc.data() as Player;
内容的提问来源于stack exchange,提问作者Nawabu
相关产品推荐
相关产品推荐

