Deno路由数据库查询函数遭遇TS2532错误:Object is possibly 'undefined'问题求助
解决Deno PostgreSQL查询中的TS2532 "Object is possibly 'undefined'"错误
我来帮你搞定这个TypeScript错误,正好我也用过这个Deno的PostgreSQL库😉
错误原因
你遇到的TS2532错误,核心问题是:当你的SELECT查询没有匹配到任何行时(比如输入的邮箱不存在),getUser.rowDescription会是undefined。TypeScript的严格类型检查不允许直接访问undefined对象的columns属性,所以触发了这个报错。
修复方案1:修复原有代码逻辑
我们需要先判断rowDescription是否存在,同时还要修复连接泄漏的问题(原来的代码在提前return或异常时不会关闭数据库连接):
const logInUser = async(inputEmail: string, inputPassword: string)=>{ try{ await client.connect(); const getUser = await client.queryArray`SELECT email,password FROM usersinfosreel WHERE email = ${inputEmail}`; const arrangeData: Record<string, unknown>[] = []; // 先判断rowDescription是否存在,再处理列映射 if (getUser.rowDescription) { getUser.rows.forEach(p => { const column: Record<string, unknown> = {}; getUser.rowDescription.columns.forEach((columnItem, i) => { column[columnItem.name] = p[i]; }); arrangeData.push(column); }); } // 检查是否找到唯一用户,同时提前关闭连接避免泄漏 if(arrangeData.length !== 1){ await client.end(); return false; } // 类型断言告诉TypeScript password是字符串类型 const checkedPassword = await bcrypt.compare(inputPassword, arrangeData[0].password as string); await client.end(); return checkedPassword; }catch(err){ console.log(err); // 异常时也要确保关闭连接,避免资源泄漏 await client.end().catch(e => console.error("Failed to close database client:", e)); return false; } }
关键修复点:
- 增加
if (getUser.rowDescription)判断,确保只有当列描述存在时才执行映射逻辑 - 替换
map为forEach(因为我们不需要返回新数组,只是遍历处理) - 给
arrangeData[0].password添加类型断言as string,解决类型不确定的问题 - 在所有提前return的分支和异常分支都添加
client.end(),避免数据库连接泄漏
修复方案2:用库的便捷方法简化代码
其实这个PostgreSQL库提供了queryObject方法,可以直接返回键值对对象数组,完全省去手动映射列的步骤,自然也不会碰到rowDescription的问题:
const logInUser = async(inputEmail: string, inputPassword: string)=>{ try{ await client.connect(); // 用queryObject直接获取结构化的对象数组 const getUser = await client.queryObject`SELECT email,password FROM usersinfosreel WHERE email = ${inputEmail}`; // 类型断言明确返回的行结构 const users = getUser.rows as { email: string, password: string }[]; if(users.length !== 1){ await client.end(); return false; } const checkedPassword = await bcrypt.compare(inputPassword, users[0].password); await client.end(); return checkedPassword; }catch(err){ console.log(err); await client.end().catch(e => console.error("Failed to close database client:", e)); return false; } }
为什么这个方案更好?
queryObject自动把查询结果转成以列名为键的对象,不用自己处理rowDescription和列映射- 代码更简洁,可读性更高,也减少了手动编写映射逻辑可能出现的错误
- 类型断言让TypeScript明确知道返回数据的结构,避免类型错误
额外建议
- 尽量避免使用
any类型,明确参数和返回值的类型(比如把inputEmail: any改成inputEmail: string),这样TypeScript的类型检查才能帮你提前发现问题 - 考虑使用数据库连接池而不是每次请求都创建新连接,频繁的connect/end会影响性能
- 确保数据库中存储的是bcrypt哈希后的密码,不要存储明文密码(你已经在用
bcrypt.compare,这一点做得很好!)
内容的提问来源于stack exchange,提问作者user16152651
相关产品推荐
相关产品推荐

