Skip to content

Instantly share code, notes, and snippets.

@Luisgustavom1
Last active October 12, 2023 22:34
Show Gist options
  • Save Luisgustavom1/cdc154c180f3969efdabb9d383ff9e26 to your computer and use it in GitHub Desktop.
Save Luisgustavom1/cdc154c180f3969efdabb9d383ff9e26 to your computer and use it in GitHub Desktop.
The purpose this code is to study about more complex type system of typescript. Its a query builder type system
interface User {
id: number;
name: string;
email: string;
password: string;
updated_at: Date;
}
interface Product {
id: number;
name: string;
description: string;
price: number;
}
interface Order {
id: number;
user_id: number;
product_id: number;
quantity: number;
created_at: Date;
}
type DB = {
user: User;
product: Product;
order: Order;
}
const myDbInstance = {} as DB;
const getUserById = async (id: number) => {
const user = await QueryBuilder.database(myDbInstance)
.from("user")
.select(["id", "email", "name"])
.where("id = :id", { id })
.build();
return user.name;
}
type QueryBuilderMethods<
DB,
Table extends keyof DB = keyof DB,
Columns extends keyof DB[Table] = keyof DB[Table],
ColumnsSelected extends Array<Columns> = Array<Columns>,
> = {
from: <T extends Table>(table: T) => QueryBuilderMethods<DB, T>,
select: <S extends Array<Columns> = Array<Columns>>(s: S) => QueryBuilderMethods<DB, Table, Columns, S>,
where: <
W extends MakeWhereString<Columns & string>,
V extends ExtractColumnByWhere<W>
>(
w: W,
v: { [K in V]: DB[Table][V & Columns] }
) => QueryBuilderMethods<DB, Table, Columns, ColumnsSelected>,
build: () => Promise<Pick<DB[Table], ColumnsSelected[number]>>
}
type MakeWhereString<
Column extends string,
Operator extends string = ComparisonOperators,
Value extends string = string
> = `${Column} ${Operator} :${Value}`;
type ComparisonOperators = "=" | "<>" | ">=" | "<=";
type ExtractColumnByWhere<Str> = Str extends MakeWhereString<infer C>
? C
: never;
declare namespace QueryBuilder {
function database<DB>(db: DB): QueryBuilderMethods<DB>;
}
interface User {
id: number;
name: string;
email: string;
password: string;
updated_at: Date;
}
interface Product {
id: number;
name: string;
description: string;
price: number;
}
interface Order {
id: number;
user_id: number;
product_id: number;
quantity: number;
created_at: Date;
}
type DB = {
user: User;
product: Product;
order: Order;
}
const myDbInstance = {} as DB;
const getUserById = async (id: number) => {
const user = await QueryBuilder.database(myDbInstance)
.from("user")
.select(["id", "email", "name"])
.where("id = :id", { id })
.build();
return user.name;
}
@Luisgustavom1
Copy link
Author

The inspiration to build this code -> How i learn typecript

Some query builder references:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment