#5699·prql

建议: TypeScript 查询构建器

作者: NickCrews创建于 2026年2月27日更新于 2026年6月5日

我希望在 TypeScript 中构建一个具有卓越、对模式感知的类型安全性的查询构建器。TLDR 类似于这样:

typescript
const penguins = prql.table('penguins', {
    "species": "string",
    "year": "int32",
    "bill_length_mm": "float64",
})

const by_year_species = penguins
    .group(
        r => [r.col("species"), r.col("year")],
        g => g
            .filter(r => r.col("bill_length_mm").is_not_null())
            .agg(
                g => ({
                    count: prql.count(),
                    mean_length: g.col("bill_length_mm").mean(),
                })
            )
    )
    .sort(r => r.col("mean_length"))
    .take(10)


const recent_longest_per_year = penguins
    .group(
        r => r.col("year"),
        g => g.sort(r => r.col("bill_length_mm").desc()).take(1)
    )
    .filter(r => r.col("bill_length_mm").gt(50))
    .derive(r => {
       bill_length_cm = r.col("bill_length_mm").div(10), // 由于 TypeScript 没有运算符重载,所以需要使用 .div() 来实现
       version = prql.sql<"string">("version()"),
     })

我来自于维护 https://GitHub.com/ibis-project/ibis 的经验,它与 prql 类似,因为它大部分是管道化的,但它确实受到 Python 没有必要跟踪关系模式的复杂类型系统的根限制。它也处于 Python 中,我希望能够在 Web 上使用它。我还在一些 Web 项目中使用了 drizzle ORMzod,我喜欢它们提供的类型安全性,它们展示了如何利用高级 TypeScript 功能来获得出色的 DX。我开始编写上面的原型实现,但我使用了 duckb 的 json_deserialize_sql() 函数将我的 IR 编译为 SQL。但这限制了我只能使用 duckdb,并且要求使用非常 SQL 类似的格式,而我的库则使用非常管道化的格式,因此需要进行大量复杂的转换。然后我想到了 PRQL,它基本上与我在用户面向的 API 中寻找的语义完全一致,并且它还解决了编译问题!因此,我希望转向使用 PRQL 作为编译器,并且在这样做时将语义与 PRQL 保持一一对应(我认为这些语义非常棒!)。

我需要解决的一些问题: