我使用的是Kysely SQL builder for JS(根据Vercel的建议,尽管文档/社区很少)。它是一个完全类型化的SQL构建器。您使用模式构造了一个db
对象,当您进行查询时,它会识别表名和属性(如果我自己这么说的话,这是非常奇特的)。
import 'dotenv/config'
import { createKysely } from '@vercel/postgres-kysely'
import { DB } from 'kysely-codegen'
export const db = createKysely<DB>()
export { sql } from 'kysely'
DB
直接从PostgreSQL模式生成,并存储在kysely-codegen
node_modules文件夹中。它看起来像这样(简短的片段):
export interface MyTable {
id: string
foo: string
bar: boolean
}
export interface DB {
my_table: MyTable
}
现在,我的问题围绕着使用select
函数,该函数接受MyTable
的键数组(当查询my_table
时)。
const record = await db
.selectFrom('my_table')
.select(['foo', 'id'])
.executeTakeFirst()
那很好但是当我这样做的时候,它不起作用:
// simulate not knowing what the input is
// as if you were making a browser JSON API request
const json = JSON.parse(fs.readFileSync('test.json'))
const selectKeys = Object.keys(json)
const record = await db
.selectFrom('my_table')
.select(selectKeys)
.executeTakeFirst()
我基本上得到了这个错误:
“string[]”类型的参数不能分配给“SelectArg<DB,“my_table”,SelectExpression<DB,“my_table”>>”类型的参数。
我可以这样修复它:
const record = await db
.selectFrom('my_table')
.select(selectKeys as Array<keyof MyTable>)
.executeTakeFirst()
我还可以在代码前面的某个地方保证selectKeys
是用my_table的键构建的,方法如下:
const MY_TABLE_KEYS: Array<keyof MyTable> = ['id', 'foo', 'bar']
function getKeys(json) {
const keys = []
for (const key in json) {
if (MY_TABLE_KEYS.includes(key)) {
keys.push(key)
}
}
return keys
}
我基本上已经将数据库接口中的键复制到了一个数组中,但是getKeys
函数有几个问题,不确定有什么方法可以解决。一个粗糙的TSPlayground在这里展示了我面临的一些挑战。
问题是,如何正确地键入要传递给.select
方法的键?
1条答案
按热度按时间tp5buhyn1#
您可能正在寻找类型 predicate /类型保护。类型 predicate 是Assert/声明参数是特定类型的函数,如果该函数返回true。在这种情况下,一个简单的 predicate 可能看起来像
在上面的简单例子中,我总是返回true。为了使它有用,你不需要检查这个键是否是你所知道的键之一。您可以使用下面的示例来获取您正在寻找的内容。
您会注意到
record[key] = json[key]
仍然有一些问题,但这是因为json[key]
可能未定义(因为它是一个部分);