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

Knex.raw在TypeScript中类型不兼容问题及正确处理方式

Knex.raw 触发TypeScript编译错误的解决方案

问题场景

维护全局数据库连接列表,获取连接后调用knex.raw时触发TypeScript编译错误,希望找到无需使用// @ts-ignore的规范解决方法。

代码示例

function getDB(config_name: string, maxConnections: number = 1): Knex {
    if (!!cfg && !!cfg.datastores && !!cfg.datastores[config_name]) {
        if (databases[config_name]) {
            return databases[config_name];
        } else {
            const config = cfg.datastores[config_name];
            const db = knex({
                client: 'pg',
                connection: config,
                pool: {min: 0, max: maxConnections},
            });
            databases[config_name] = db;
            return db;
        }
    } else {
        throw new Error('config not initialized, can\'t load db');
    }
}

// 调用处
const theDb = getDB('whatever');
theDb
    .from('customer')
    .select('*')
    .whereILike(bondinet_db.raw('CAST(c.customer_number AS text)'), '%1%');

编译错误信息

Overload 1 of 18, '(columnName: never, value: Readonly<Raw<never>> | null): QueryBuilder<{}, DeferredKeySelection<{}, string, false, {}, false, {}, never>[]>', gave the following error.
    Argument of type 'Raw<any>' is not assignable to parameter of type 'never'.
  Overload 2 of 18, '(columnName: string, value: Value): QueryBuilder<{}, DeferredKeySelection<{}, string, false, {}, false, {}, never>[]>', gave the following error.
    Argument of type 'Raw<any>' is not assignable to parameter of type 'string'.
  Overload 3 of 18, '(sql: string, bindings?: ValueDict | RawBinding | readonly RawBinding[] | undefined): QueryBuilder<{}, DeferredKeySelection<{}, string, false, {}, false, {}, never>[]>', gave the following error.
    Argument of type 'Raw<any>' is not assignable to parameter of type 'string'.

解决方案

不需要依赖// @ts-ignore,可以通过以下规范方式解决:

1. 使用whereRaw替代whereILike适配Raw表达式

whereILike的参数类型设计是接收列名字符串和匹配值,不支持直接传入Raw实例。如果需要对Raw表达式执行模糊匹配,改用whereRaw更符合Knex的类型设计:

theDb
    .from('customer')
    .select('*')
    .whereRaw('CAST(c.customer_number AS text) ILIKE ?', ['%1%']);

这种写法既满足业务需求,又能让TypeScript正确推导类型,避免编译错误。

2. 给getDB函数指定精确的泛型类型

当前getDB返回的是泛型Knex实例,TypeScript无法推断出具体表的结构信息,导致类型校验严格度过高。可以给getDB添加泛型参数,让返回的Knex实例关联具体表的类型:

// 先定义customer表的类型接口
interface CustomerTable {
    customer_number: number;
    // 其他字段...
}

function getDB<T = unknown>(config_name: string, maxConnections: number = 1): Knex<T> {
    // 原函数逻辑不变
}

// 调用时指定表类型
const theDb = getDB<CustomerTable>('whatever');

通过泛型约束,TypeScript能更准确地推断查询方法的参数类型,减少不必要的类型错误。

3. 类型断言(临时方案)

如果必须保留whereILike的写法,可以对Raw实例进行类型断言,但这是退而求其次的方案,不如前两种规范:

theDb
    .from('customer')
    .select('*')
    .whereILike(bondinet_db.raw('CAST(c.customer_number AS text)') as unknown as string, '%1%');

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 17:07:55