Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save belgattitude/1d797ffab436bab09a209acdea8a3400 to your computer and use it in GitHub Desktop.
Save belgattitude/1d797ffab436bab09a209acdea8a3400 to your computer and use it in GitHub Desktop.
typescript-issue-with-async-discriminated-union
import type { Compilable, InferResult, Kysely } from 'kysely';
type QueryResultSuccess<T> = {
success: true;
data: T;
};
type QueryResultError = {
success: false;
errorMsg: string;
};
type QueryResult<T> = QueryResultSuccess<T> | QueryResultError;
type AsyncQueryResult<T> = Promise<QueryResult<T>>;
type DB = {
product: {
id: number;
name: string;
};
};
class Datasource<TDatabase = DB> {
constructor(public kysely: Kysely<TDatabase>) {}
query = async <TFn extends () => any, TData = ReturnType<TFn>>(
fn: TFn
): AsyncQueryResult<TData> => {
return this.createQueryResultSuccess<TData>(fn());
};
queryKysely = async <
TQuery extends Compilable<unknown>,
TData = InferResult<TQuery>,
>(
query: TQuery
): AsyncQueryResult<TData> => {
try {
const r = await this.kysely.executeQuery(query);
return this.createQueryResultSuccess<TData>(r.rows as TData);
} catch (err) {
return this.createQueryResultError(err as Error);
}
};
protected createQueryResultSuccess = <T>(data: T): QueryResultSuccess<T> => {
return {
success: true,
data: data,
};
};
protected createQueryResultError = (err: Error): QueryResultError => {
return {
success: false,
errorMsg: err.message,
};
};
}
type Product = {
id: number;
name: string;
description: string;
};
class Repo {
constructor(private ds: Datasource) {}
search = async (): AsyncQueryResult<Product[]> => {
// ts-expect-error shoudl give an error cause id aren't the same types
type IncompleteProduct = {
id: number;
name: string;
};
const incompleteProduct: IncompleteProduct = {
id: 1,
name: 'Incomplete Product',
};
const getIncompleteProducts = (): IncompleteProduct[] => {
return [incompleteProduct];
};
return this.ds.query(getIncompleteProducts);
const a = await this.ds.query(getIncompleteProducts);
if (a.success) {
const _z = a.data[0]?.id;
}
return a;
};
searchKysely = async (): AsyncQueryResult<Product[]> => {
const query = this.ds.kysely.selectFrom('product').select(['id', 'name']);
const a = await this.ds.queryKysely(query);
return a;
// return await this.ds.queryKysely(query);
// return this.ds.queryKysely(query);
};
}
const kysely = {} as unknown as Kysely<DB>;
const repo = new Repo(new Datasource(kysely));
const testTypes = async () => {
const result = await repo.search();
const _idOrErrMessage = result.success
? result.data[0]?.id
: result.error.messsage;
const result2 = await repo.searchKysely();
const _idOrErrMessage2 = result2.success
? result2.data[0]?.id
: result2.error.messsage;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment