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
相关产品推荐
相关产品推荐

