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

扩展Knex返回非QueryBuilder实例时触发TypeScript错误

解决Knex扩展QueryBuilder返回非QueryBuilder类型的TypeScript错误

问题场景

尝试给Knex的QueryBuilder添加toPrismaSql方法,将Knex查询转换为Prisma.Sql对象(类似.toSQL()的非链式返回逻辑),但触发TypeScript类型错误,提示返回的Sql类型无法匹配QueryBuilder或Promise相关类型要求。

原代码

import Knex from 'knex'
import { Prisma } from '@prisma/client'

Knex.QueryBuilder.extend('toPrismaSql', function() {
  const { bindings, sql } = this.toSQL()
  
  if (sql.includes('??')) {
    throw new Error(`Cannot convert identifiers ??. SQL query: ${sql}`)
  }

  return Prisma.sql(sql.split('?'), ...bindings)
})

export const knex = Knex({ client: 'postgres' })

TypeScript错误信息

Argument of type
<
  TRecord extends {} = any,
  TResult extends {} = unknown[]
>(
  this: QueryBuilder<TRecord, TResult>
) => Sql

is not assignable to parameter of type

<
  TRecord extends {} = any,
  TResult extends {} = unknown[]
>(
  this: QueryBuilder<TRecord, TResult>,
  ...args: any[]
) => QueryBuilder<TRecord, TResult>
  | Promise<Resolve<TResult> | QueryBuilder<TRecord | TResult, any>>

Type 'Sql' is not assignable to type 'QueryBuilder<TRecord, TResult> | Promise<Resolve<TResult> | QueryBuilder<TRecord | TResult, any>>

ts(2345)

解决方案

1. 添加Knex类型扩展声明

创建knex.d.ts类型声明文件,扩展QueryBuilder接口,定义自定义方法的返回类型:

import Knex from 'knex'
import { Prisma } from '@prisma/client'

declare module 'knex' {
  interface QueryBuilder<TRecord extends {} = any, TResult extends {} = unknown[]> {
    toPrismaSql(): Prisma.Sql
  }
}

2. 调整原代码引入类型声明

修改原代码,确保类型声明被TypeScript识别(若项目中未自动加载,需调整tsconfig.json的include配置,加入该声明文件路径):

import Knex from 'knex'
import { Prisma } from '@prisma/client'
import './knex.d.ts'

Knex.QueryBuilder.extend('toPrismaSql', function() {
  const { bindings, sql } = this.toSQL()
  
  if (sql.includes('??')) {
    throw new Error(`Cannot convert identifiers ??. SQL query: ${sql}`)
  }

  return Prisma.sql(sql.split('?'), ...bindings)
})

export const knex = Knex({ client: 'postgres' })

原理说明

Knex的默认TypeScript定义约束了扩展方法必须返回QueryBuilder实例或Promise,但我们的方法需要返回Prisma.Sql。通过扩展Knex的模块类型声明,手动告知TypeScripttoPrismaSql方法的正确返回类型,即可解决类型不兼容问题。

内容的提问来源于stack exchange,提问作者Pierre Noël

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 19:28:19