edgedb-js
edgedb-js copied to clipboard
Export additional utility types from generated query builder code
I'm attempting to write generic functions that accept query builder expressions and wrap them with additional functionality before calling them. (In our particular case, the intent is to combine with Effect to perform logging/tracing/etc and turn the expression call into an "effect-ful" call, but I could imagine loads of other use cases).
However, I am occasionally having difficulty crafting type signatures that satisfy TS. For example, this works:
import { type $expr_Insert } from "@internal/edgedb/edgeql/insert";
import {
type ObjectType,
} from "@internal/edgedb/edgeql/typesystem";
export const tryInsert = async <T extends ObjectType>(
statement: $expr_Insert<T>,
): Promise<string> => {
try {
const result = (await statement.run(client)) as unknown as { id: string };
return result.id;
} catch (error) {
console.error(error);
throw error;
}
};
For whatever reason, statement.run()
has an any
return type, in spite of being an $expr_Insert
- so the clunky cast is required, but works fine. Also, this is obviously a fairly contrived example, but picture additional things happening in the wrapper.
However, the following seems to be impossible:
import { type $expr_Insert } from "@internal/edgedb/edgeql/insert";
import {
type $expr_WithParams,
// INVALID: type is NOT exported
type paramsToParamArgs,
// INVALID: type is NOT exported
type ParamsRecord,
} from "@internal/edgedb/edgeql/params";
import {
type ObjectType,
} from "@internal/edgedb/edgeql/typesystem";
export const tryInsertWithParams = async <
T extends ObjectType,
// INVALID: ParamsRecord is not available
P extends ParamsRecord,
>(
statement: $expr_WithParams<P, $expr_Insert<T>>,
// INVALID: paramsToParamArgs is not available
args: paramsToParamArgs<P>,
): Promise<string> => {
try {
const result = (await statement.run(client, args)) as unknown as {
id: string;
};
return result.id;
} catch (error) {
console.error(error);
throw error;
}
};
The two utility types paramsToParamArgs
and ParamsRecord
are not exported from the generated code. Therefore, it does not seem possible to correctly type generic parameters to wrap a parameterized expression execution.
I tried copy/pasting the definitions across alongside the above code, but it complains about args
being a different type than expected:
Argument of type 'paramsToParamArgs<Params>' is not assignable to parameter of type 'paramsToParamArgs<Params>'.
Type 'paramsToParamArgs<Params>' is not assignable to type '{ [key in keyof Params as Params[key] extends ParamType ? key : never]: Params[key] extends ParamType ? Readonly<BaseTypeToTsType<Params[key], true>> : never; }'.ts(2345)
(First type is the copied type, second is the type in the generated code).
Open to other ideas about how to achieve this, but it seems the easiest solution would be to export additional types from the generated code.