You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 16:07:37