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

TypeScript中oracledb的execute()方法为何返回unknown类型?

解决oracledb execute返回unknown类型导致outBinds类型错误的问题

问题描述

调用存储过程后访问返回的游标p_activerecords时,触发TypeScript错误:

'dbresult.outBinds' is of type 'unknown'.ts(18046)

根源是dbconn.execute()的返回类型被识别为unknown。虽然可以通过声明dbresult: any临时规避,但希望通过正确的类型处理让execute返回OracleDB.Result类型,避免使用any。

用户原始代码示例:

import { dashboardRecord, dashboardRecordsRequest, dashboardRecordsResponse } from "datamodel/dashboard/dashboard";
import { logger } from "logger/logger";
import OracleDB from "oracledb";

export async function getActiveRequestRecords(dashboardRecordsRequest: dashboardRecordsRequest): Promise<dashboardRecordsResponse> {
    let dashboardRecordsResponse: dashboardRecordsResponse;
    dashboardRecordsResponse = {
        message: "",
        records: [],
        request: dashboardRecordsRequest,
        totalRecords: 0,
    }
    const sql: string = `BEGIN get_dashboard_active_request_records(:p_entityname, :p_sortby, :p_sortorder, :p_startindex, :p_pagesize, :p_totalrecords, :p_activerecords); END;`;
    const p_entityname: OracleDB.BindParameter = { dir: OracleDB.BIND_IN, val: dashboardRecordsRequest.entityName, type: OracleDB.STRING };
    const p_sortby: OracleDB.BindParameter = { dir: OracleDB.BIND_IN, val: dashboardRecordsRequest.sortBy, type: OracleDB.STRING };
    const p_sortOrder: OracleDB.BindParameter = { dir: OracleDB.BIND_IN, val: dashboardRecordsRequest.sortOrder, type: OracleDB.STRING };
    const p_startindex: OracleDB.BindParameter = { dir: OracleDB.BIND_IN, val: dashboardRecordsRequest.startIndex, type: OracleDB.NUMBER };
    const p_pagesize: OracleDB.BindParameter = { dir: OracleDB.BIND_IN, val: dashboardRecordsRequest.pageSize, type: OracleDB.NUMBER };
    const p_totalrecords: OracleDB.BindParameter = { dir: OracleDB.BIND_OUT, type: OracleDB.NUMBER };
    const p_activerecords: OracleDB.BindParameter = { dir: OracleDB.BIND_OUT, type: OracleDB.CURSOR };
    const bindVar: OracleDB.BindParameter[] = [
        p_entityname,
        p_sortby,
        p_sortOrder,
        p_startindex,
        p_pagesize,
        p_totalrecords,
        p_activerecords
    ];
    const options: OracleDB.ExecuteOptions = { outFormat: OracleDB.OUT_FORMAT_OBJECT };

    try {
        const dbconn = await OracleDB.getConnection('requestpool');
        const dbresult = await dbconn.execute(sql, bindVar, options);
        const activerecords = dbresult.outBinds.p_activerecords;
        const rows = await activerecords?.getRows();
        dashboardRecordsResponse.totalRecords = dbresult.outBinds.p_totalrecords;

        let dashboardRecord: dashboardRecord;
        for (const row of rows) {
            dashboardRecord = {
                approvedDate: row.ACTIONDATE,
                creationDate: new Date(Date.now()),
                employeeGEN: '',
                employeeName: '',
                lastActionDate: row.ACTIONDATE,
                pendingWith: row.PENDINGWITH,
                processType: row.PROCESSTYPE,
                requestNumber: row.REQUESTNUMBER,
                requestorName: row.REQUESTOR,
                requestState: row.REQUESTSTATUS,
                submissionDate: new Date(Date.now()),
                withdrawnDate: new Date(Date.now()),
            }
            dashboardRecordsResponse.records?.push(dashboardRecord);
        }
        await dbconn.close();
    } catch (err) {
        dashboardRecordsResponse.message = 'Error while retrieving Active Request records.';
        logger.error(err);
    }
    console.log(dashboardRecordsResponse);
    return dashboardRecordsResponse;
}

解决方案

1. 显式指定execute方法的泛型参数

oracledb的execute方法支持泛型参数,通过指定泛型可以明确返回的Result类型,特别是outBinds的结构:

首先定义outBinds的类型接口:

// 定义存储过程输出参数的类型结构
interface ActiveRequestOutBinds {
  p_totalrecords: number;
  p_activerecords: OracleDB.RefCursor;
}

然后在调用execute时传入泛型参数:

// 第一个泛型参数是行数据类型(不需要可设为unknown),第二个是outBinds类型
const dbresult = await dbconn.execute<unknown, ActiveRequestOutBinds>(sql, bindVar, options);

这样TypeScript就能正确识别dbresult.outBinds的类型,不再是unknown,访问p_activerecords和p_totalrecords时也不会报错。

2. 优化绑定变量定义(可选)

将绑定变量从数组改为对象形式,参数名与存储过程的参数一一对应,不仅更直观,还能让TypeScript更好地关联参数名和类型:

const bindVars = {
  p_entityname: { dir: OracleDB.BIND_IN, val: dashboardRecordsRequest.entityName, type: OracleDB.STRING },
  p_sortby: { dir: OracleDB.BIND_IN, val: dashboardRecordsRequest.sortBy, type: OracleDB.STRING },
  p_sortorder: { dir: OracleDB.BIND_IN, val: dashboardRecordsRequest.sortOrder, type: OracleDB.STRING },
  p_startindex: { dir: OracleDB.BIND_IN, val: dashboardRecordsRequest.startIndex, type: OracleDB.NUMBER },
  p_pagesize: { dir: OracleDB.BIND_IN, val: dashboardRecordsRequest.pageSize, type: OracleDB.NUMBER },
  p_totalrecords: { dir: OracleDB.BIND_OUT, type: OracleDB.NUMBER },
  p_activerecords: { dir: OracleDB.BIND_OUT, type: OracleDB.CURSOR }
};

3. 修改后的完整代码

import { dashboardRecord, dashboardRecordsRequest, dashboardRecordsResponse } from "datamodel/dashboard/dashboard";
import { logger } from "logger/logger";
import OracleDB from "oracledb";

// 定义存储过程输出参数的类型结构
interface ActiveRequestOutBinds {
  p_totalrecords: number;
  p_activerecords: OracleDB.RefCursor;
}

export async function getActiveRequestRecords(dashboardRecordsRequest: dashboardRecordsRequest): Promise<dashboardRecordsResponse> {
    let dashboardRecordsResponse: dashboardRecordsResponse = {
        message: "",
        records: [],
        request: dashboardRecordsRequest,
        totalRecords: 0,
    };
    const sql: string = `BEGIN get_dashboard_active_request_records(:p_entityname, :p_sortby, :p_sortorder, :p_startindex, :p_pagesize, :p_totalrecords, :p_activerecords); END;`;
    
    const bindVars = {
        p_entityname: { dir: OracleDB.BIND_IN, val: dashboardRecordsRequest.entityName, type: OracleDB.STRING },
        p_sortby: { dir: OracleDB.BIND_IN, val: dashboardRecordsRequest.sortBy, type: OracleDB.STRING },
        p_sortorder: { dir: OracleDB.BIND_IN, val: dashboardRecordsRequest.sortOrder, type: OracleDB.STRING },
        p_startindex: { dir: OracleDB.BIND_IN, val: dashboardRecordsRequest.startIndex, type: OracleDB.NUMBER },
        p_pagesize: { dir: OracleDB.BIND_IN, val: dashboardRecordsRequest.pageSize, type: OracleDB.NUMBER },
        p_totalrecords: { dir: OracleDB.BIND_OUT, type: OracleDB.NUMBER },
        p_activerecords: { dir: OracleDB.BIND_OUT, type: OracleDB.CURSOR }
    };
    
    const options: OracleDB.ExecuteOptions = { outFormat: OracleDB.OUT_FORMAT_OBJECT };

    try {
        const dbconn = await OracleDB.getConnection('requestpool');
        // 指定泛型参数,明确返回类型
        const dbresult = await dbconn.execute<unknown, ActiveRequestOutBinds>(sql, bindVars, options);
        const activerecords = dbresult.outBinds.p_activerecords;
        const rows = await activerecords?.getRows();
        dashboardRecordsResponse.totalRecords = dbresult.outBinds.p_totalrecords;

        if (rows) {
            for (const row of rows) {
                const dashboardRecord: dashboardRecord = {
                    approvedDate: row.ACTIONDATE,
                    creationDate: new Date(Date.now()),
                    employeeGEN: '',
                    employeeName: '',
                    lastActionDate: row.ACTIONDATE,
                    pendingWith: row.PENDINGWITH,
                    processType: row.PROCESSTYPE,
                    requestNumber: row.REQUESTNUMBER,
                    requestorName: row.REQUESTOR,
                    requestState: row.REQUESTSTATUS,
                    submissionDate: new Date(Date.now()),
                    withdrawnDate: new Date(Date.now()),
                };
                dashboardRecordsResponse.records.push(dashboardRecord);
            }
        }
        await dbconn.close();
    } catch (err) {
        dashboardRecordsResponse.message = 'Error while retrieving Active Request records.';
        logger.error(err);
    }
    console.log(dashboardRecordsResponse);
    return dashboardRecordsResponse;
}

内容的提问来源于stack exchange,提问作者Ranjeet

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 07:23:16