用于SQL查询的Typescript可链接API

时间:2018-10-22 17:28:24

标签: typescript

是否可以使用Typescript做类似的事情:

class DSL {

    private sql: string = '';

    get book(): IBook {
        ...
    }

    get author(): IAuthor {
        ...
    }

    get eq(val: string): {
        // Add eq to book/author numbers
    }

    get gt(val: number): {
        // Add gt to book/author numbers
    }

    sql(); // Output the final sql query and return it
}

我最终想写些类似的东西:

 new DSL().author.name.eq('bob').and.age.gt(20).sql()

并输出:

SELECT * FROM AUTHORS WHERE name = 'bob' AND age > 20

在键入对象时,我很难为每个对象属性应用方法(等式,gt ...)。

1 个答案:

答案 0 :(得分:3)

根据您要编写查询的方式,将对输入内容进行一些编辑。

从您要编写查询的方式开始,我们推断author应该是与IAuthor形状相同的对象(即具有所有属性),但是每个属性都应该是一个对象具有适当的可能运算符作为方法,接受比较器值。

从那里我们需要返回一个带有所有可能的布尔运算符的对象,并且该对象的返回类型使我们回到原始状态。

让它适用于所有可能的组合是一项艰巨的任务,因此,SO并不是此论坛,但是适合您的示例并应帮助您入门的东西看起来像这样:

type Fields<T> = {
    [P in keyof T] : Operators<T[P], T>
}

type Operators<TValue, TReturn> = {
    eq(value: TValue):  BoolOperators<TReturn>
    gt(value: TValue):  BoolOperators<TReturn>
}

type BoolOperators<T> = {
    and: Fields<T>,
    or : Fields<T>
    sql(): string;
}

interface IAuthor {
    name: string;
    age: number;
}
class DSL {
    get author(): Fields<IAuthor> {
        return null as any // insert reasonable implementation, since the members of the interface are not known at runtime I would suggest a Proxy approach
    }
}

new DSL().author.name.eq('bob').and.age.gt(20).sql() // ok 
new DSL().author.name.eq('bob').and.age.gt("20").sql() // error

希望这会有所帮助,如果您陷入细节中,可以随时提出后续问题,但是上面的代码演示了通用方法。