#How let typescript infer the type ?
26 messages · Page 1 of 1 (latest)
Preview:```ts
type SelectQueryBuilder<A, B, C> = any
interface DefineBlockAnalyticParams<DB> {
qb: (db: DB) => SelectQueryBuilder<DB, any, any>;
transform(data: Awaited<ReturnType<this['qb']>>['execute']): any;
}
const defineBlockAnalytic = <DB>(
params: DefineBlockAnalyticParams<DB>,
...```
Preview:```ts
type SelectQueryBuilder<A, B, C> = {
execute: B
}
interface DefineBlockAnalyticParams<
DB,
QbRes extends SelectQueryBuilder<DB, any, any>
{
qb: (db: DB) => QbRes
transform(data: Awaited<QbRes>["execute"]): any
}
const defineBlockAnalytic = <
DB,
QbRes extends SelectQueryBuilder<DB, any, any>
...```
if you don't mind the function and the interface DefineBlockAnalyticParams accepting one more generic parameter, you can write a code like this
Yeah i would like avoid doing it.
export const AvgVolumeForPeriodAnalytic =
defineBlockAnalytic<TripDestinationSchema>({
qb: (db) => {
const qb = db
.selectFrom('trip_point')
.innerJoin('trip', 'trip.id', 'trip_point.trip_id')
.innerJoin('trip_info', 'trip_info.id', 'trip.id')
.innerJoin(
'trip_point_info',
'trip_point_info.from_id',
'trip_point.id',
)
.select((eb) =>
sql<number>`DATE_TRUNC('day', ${eb.ref('trip_point.timestamp')})`.as(
'day',
),
)
.select(({ fn }) => fn.countAll<number>().as('point_count'))
.select('vehicle_type')
.groupBy(['trip.vehicle_type', 'day'])
.orderBy('day', 'asc');
return qb;
},
transform: (data) => {},
});
That the output i woudl like write, qb is a kysely query builder and the output is qutie complexe.
Currently how i trick it is type the db of QB instead of passing it to type:
export const AvgVolumeForPeriodAnalytic = defineBlockAnalytic({
qb: (db: Kysely<TripDestinationSchema>) => {
const qb = db
.selectFrom('trip_point')
.innerJoin('trip', 'trip.id', 'trip_point.trip_id')
.innerJoin('trip_info', 'trip_info.id', 'trip.id')
.innerJoin('trip_point_info', 'trip_point_info.from_id', 'trip_point.id')
.select((eb) =>
sql<number>`DATE_TRUNC('day', ${eb.ref('trip_point.timestamp')})`.as(
'day',
),
)
.select(({ fn }) => fn.countAll<number>().as('point_count'))
.select('vehicle_type')
.groupBy(['trip.vehicle_type', 'day'])
.orderBy('day', 'asc');
return qb;
},
transform: (data) => {},
});
do the trick but maybe a way exist to improve ?
doesn't the query builder (library?) have an interface that contains execute? i guess there is an interface for that and has a generic parameter for execute...
Preview:```ts
type HasExecute<T> = {
// the interface that have execute
execute: T
}
interface DefineBlockAnalyticParams<DB, Res> {
qb: (db: DB) => HasExecute<Res>
transform(data: Res): any
}
const defineBlockAnalytic = <DB, Res>(
params: DefineBlockAnalyticParams<DB, Re
...```
Yep cant really do that :/
Don't know how say it properly, but i would like restrict the type of the output but let ts do their job. Like "satisfies" key work like:
"i would like an object, with 2 parameters, qb, that should be a function that take "db", an instance of "Kysely<DB>" and any params, and transform that take the result of "QB" and return anything"
export interface DefineBlockAnalyticParams<DB> {
qb: (db: Kysely<DB>, ...params: any) => SelectQueryBuilder<DB, any, any>;
transform(data: Awaited<ReturnType<ReturnType<this['qb']>['execute']>>): any;
}
But if i do that TS don't infer anymore qb & transform and "force" the type to what i have defined, but it's more a constraint that a real output.
I try "satisfies" and this kind of things but no success T..T
for declarations(e.g. const foo = {...}), yeah, you are right; satisfies is the solution. but for function arguments, the solution is generics.
generics do exactly what you want, why you don't wanna apply it?
I have do that:
import { Kysely, SelectQueryBuilder } from 'kysely';
export interface DefineBlockAnalyticParams<
DB,
QB extends SelectQueryBuilder<DB, any, any>,
O,
> {
qb: (db: Kysely<DB>, ...params: any) => QB;
transform(data: Awaited<ReturnType<ReturnType<this['qb']>['execute']>>): O;
}
export function defineBlockAnalytic<
DB,
QB extends SelectQueryBuilder<DB, any, any>,
O,
>(params: DefineBlockAnalyticParams<DB, QB, O>) {
return params;
}
And work well for qb & transform
but i loose the output (O)
does transform return the proper type on declaration part?
Getting unknow but
import { Kysely, SelectQueryBuilder } from 'kysely';
export interface DefineBlockAnalyticParams<
DB,
QB extends SelectQueryBuilder<DB, any, any>,
QBParams extends any[],
O,
> {
qb: (db: Kysely<DB>, ...params: QBParams) => QB;
transform: (
data: Awaited<ReturnType<ReturnType<this['qb']>['execute']>>,
) => O;
}
export function defineBlockAnalytic<
DB,
QB extends SelectQueryBuilder<DB, any, any>,
QBParams extends any[],
O,
>(params: DefineBlockAnalyticParams<DB, QB, QBParams, O>) {
return params;
}
This is the updated type i use
Look liks is because Awaited<ReturnType<ReturnType<this['qb']>['execute']>> is ambigous
import { Kysely, SelectQueryBuilder } from 'kysely';
export interface DefineBlockAnalyticParams<
DB,
QB extends SelectQueryBuilder<DB, any, any>,
QBParams extends any[],
QBResult extends Awaited<
ReturnType<SelectQueryBuilder<DB, any, any>['execute']>
>,
O,
> {
qb: (db: Kysely<DB>, ...params: QBParams) => QB;
transform: (data: QBResult) => O;
}
export function defineBlockAnalytic<
DB,
QB extends SelectQueryBuilder<DB, any, any>,
R extends Awaited<ReturnType<QB['execute']>>,
QBParams extends any[],
O,
>(params: DefineBlockAnalyticParams<DB, QB, QBParams, R, O>) {
return params;
}
Fixed type 🥲
wait, you can write just QB instead of ReturnType<this['qb']>
import { Kysely, SelectQueryBuilder } from 'kysely';
export interface DefineBlockAnalyticParams<
DB,
QB extends SelectQueryBuilder<DB, any, any>,
QBParams extends any[],
QBResult extends Awaited<ReturnType<QB['execute']>>,
O,
> {
qb: (db: Kysely<DB>, ...params: QBParams) => QB;
transform: (data: QBResult) => O;
}
export function defineBlockAnalytic<
DB,
QB extends SelectQueryBuilder<DB, any, any>,
QBResult extends Awaited<ReturnType<QB['execute']>>,
QBParams extends any[],
O,
>(params: DefineBlockAnalyticParams<DB, QB, QBParams, QBResult, O>) {
return params;
}
and QBResult is not necessary to be a generic parameter, just inline it